mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Initial VS Code 1.19 source merge (#571)
* Initial 1.19 xcopy * Fix yarn build * Fix numerous build breaks * Next batch of build break fixes * More build break fixes * Runtime breaks * Additional post merge fixes * Fix windows setup file * Fix test failures. * Update license header blocks to refer to source eula
This commit is contained in:
@@ -6,11 +6,10 @@
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export const CONFIG_DEFAULT_NAME = 'settings';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
export const WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME = '.sqlops';
|
||||
export const WORKSPACE_CONFIG_DEFAULT_PATH = `${WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME}/${CONFIG_DEFAULT_NAME}.json`;
|
||||
export const FOLDER_CONFIG_FOLDER_NAME = '.sqlops';
|
||||
export const FOLDER_SETTINGS_NAME = 'settings';
|
||||
export const FOLDER_SETTINGS_PATH = `${FOLDER_CONFIG_FOLDER_NAME}/${FOLDER_SETTINGS_NAME}.json`;
|
||||
|
||||
export const IWorkspaceConfigurationService = createDecorator<IWorkspaceConfigurationService>('configurationService');
|
||||
|
||||
@@ -29,6 +28,6 @@ export const folderSettingsSchemaId = 'vscode://schemas/settings/folder';
|
||||
export const TASKS_CONFIGURATION_KEY = 'tasks';
|
||||
export const LAUNCH_CONFIGURATION_KEY = 'launch';
|
||||
|
||||
export const WORKSPACE_STANDALONE_CONFIGURATIONS = {};
|
||||
WORKSPACE_STANDALONE_CONFIGURATIONS[TASKS_CONFIGURATION_KEY] = `${WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME}/tasks.json`;
|
||||
WORKSPACE_STANDALONE_CONFIGURATIONS[LAUNCH_CONFIGURATION_KEY] = `${WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME}/launch.json`;
|
||||
export const WORKSPACE_STANDALONE_CONFIGURATIONS = Object.create(null);
|
||||
WORKSPACE_STANDALONE_CONFIGURATIONS[TASKS_CONFIGURATION_KEY] = `${FOLDER_CONFIG_FOLDER_NAME}/tasks.json`;
|
||||
WORKSPACE_STANDALONE_CONFIGURATIONS[LAUNCH_CONFIGURATION_KEY] = `${FOLDER_CONFIG_FOLDER_NAME}/launch.json`;
|
||||
@@ -52,46 +52,7 @@ const configurationEntrySchema: IJSONSchema = {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// BEGIN VSCode extension point `configuration`
|
||||
const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint<IConfigurationNode>('configuration', [], {
|
||||
description: nls.localize('vscode.extension.contributes.configuration', 'Contributes configuration settings.'),
|
||||
oneOf: [
|
||||
configurationEntrySchema,
|
||||
{
|
||||
type: 'array',
|
||||
items: configurationEntrySchema
|
||||
}
|
||||
]
|
||||
});
|
||||
configurationExtPoint.setHandler(extensions => {
|
||||
const configurations: IConfigurationNode[] = [];
|
||||
|
||||
function handleConfiguration(node: IConfigurationNode, id: string, extension: IExtensionPointUser<any>) {
|
||||
let configuration = objects.clone(node);
|
||||
|
||||
if (configuration.title && (typeof configuration.title !== 'string')) {
|
||||
extension.collector.error(nls.localize('invalid.title', "'configuration.title' must be a string"));
|
||||
}
|
||||
|
||||
validateProperties(configuration, extension);
|
||||
|
||||
configuration.id = id;
|
||||
configurations.push(configuration);
|
||||
};
|
||||
|
||||
for (let extension of extensions) {
|
||||
const value = <IConfigurationNode | IConfigurationNode[]>extension.value;
|
||||
const id = extension.description.id;
|
||||
if (!Array.isArray(value)) {
|
||||
handleConfiguration(value, id, extension);
|
||||
} else {
|
||||
value.forEach(v => handleConfiguration(v, id, extension));
|
||||
}
|
||||
}
|
||||
configurationRegistry.registerConfigurations(configurations, false);
|
||||
});
|
||||
// END VSCode extension point `configuration`
|
||||
let registeredDefaultConfigurations: IDefaultConfigurationExtension[] = [];
|
||||
|
||||
// BEGIN VSCode extension point `configurationDefaults`
|
||||
const defaultConfigurationExtPoint = ExtensionsRegistry.registerExtensionPoint<IConfigurationNode>('configurationDefaults', [], {
|
||||
@@ -107,18 +68,58 @@ const defaultConfigurationExtPoint = ExtensionsRegistry.registerExtensionPoint<I
|
||||
}
|
||||
});
|
||||
defaultConfigurationExtPoint.setHandler(extensions => {
|
||||
const defaultConfigurations: IDefaultConfigurationExtension[] = extensions.map(extension => {
|
||||
registeredDefaultConfigurations = extensions.map(extension => {
|
||||
const id = extension.description.id;
|
||||
const name = extension.description.name;
|
||||
const defaults = objects.clone(extension.value);
|
||||
const defaults = objects.deepClone(extension.value);
|
||||
return <IDefaultConfigurationExtension>{
|
||||
id, name, defaults
|
||||
};
|
||||
});
|
||||
configurationRegistry.registerDefaultConfigurations(defaultConfigurations);
|
||||
});
|
||||
// END VSCode extension point `configurationDefaults`
|
||||
|
||||
|
||||
// BEGIN VSCode extension point `configuration`
|
||||
const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint<IConfigurationNode>('configuration', [defaultConfigurationExtPoint], {
|
||||
description: nls.localize('vscode.extension.contributes.configuration', 'Contributes configuration settings.'),
|
||||
oneOf: [
|
||||
configurationEntrySchema,
|
||||
{
|
||||
type: 'array',
|
||||
items: configurationEntrySchema
|
||||
}
|
||||
]
|
||||
});
|
||||
configurationExtPoint.setHandler(extensions => {
|
||||
const configurations: IConfigurationNode[] = [];
|
||||
|
||||
function handleConfiguration(node: IConfigurationNode, id: string, extension: IExtensionPointUser<any>) {
|
||||
let configuration = objects.deepClone(node);
|
||||
|
||||
if (configuration.title && (typeof configuration.title !== 'string')) {
|
||||
extension.collector.error(nls.localize('invalid.title', "'configuration.title' must be a string"));
|
||||
}
|
||||
|
||||
validateProperties(configuration, extension);
|
||||
|
||||
configuration.id = id;
|
||||
configurations.push(configuration);
|
||||
}
|
||||
|
||||
for (let extension of extensions) {
|
||||
const value = <IConfigurationNode | IConfigurationNode[]>extension.value;
|
||||
const id = extension.description.id;
|
||||
if (!Array.isArray(value)) {
|
||||
handleConfiguration(value, id, extension);
|
||||
} else {
|
||||
value.forEach(v => handleConfiguration(v, id, extension));
|
||||
}
|
||||
}
|
||||
configurationRegistry.registerConfigurations(configurations, registeredDefaultConfigurations, false);
|
||||
});
|
||||
// END VSCode extension point `configuration`
|
||||
|
||||
function validateProperties(configuration: IConfigurationNode, extension: IExtensionPointUser<any>): void {
|
||||
let properties = configuration.properties;
|
||||
if (properties) {
|
||||
@@ -148,6 +149,7 @@ function validateProperties(configuration: IConfigurationNode, extension: IExten
|
||||
|
||||
const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
|
||||
jsonRegistry.registerSchema('vscode://schemas/workspaceConfig', {
|
||||
allowComments: true,
|
||||
default: {
|
||||
folders: [
|
||||
{
|
||||
@@ -208,4 +210,4 @@ jsonRegistry.registerSchema('vscode://schemas/workspaceConfig', {
|
||||
},
|
||||
additionalProperties: false,
|
||||
errorMessage: nls.localize('unknownWorkspaceProperty', "Unknown workspace configuration property")
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,190 +4,130 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { clone, equals } from 'vs/base/common/objects';
|
||||
import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget, IConfigurationModel, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationModel, Configuration as BaseConfiguration, CustomConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { equals } from 'vs/base/common/objects';
|
||||
import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget, IConfigurationModel, IConfigurationOverrides, IOverrides } from 'vs/platform/configuration/common/configuration';
|
||||
import { Configuration as BaseConfiguration, ConfigurationModelParser, ConfigurationChangeEvent, ConfigurationModel, AbstractConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IConfigurationRegistry, IConfigurationPropertySchema, Extensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { WORKSPACE_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { IStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { Workspace } from 'vs/platform/workspace/common/workspace';
|
||||
import { StrictResourceMap } from 'vs/base/common/map';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
|
||||
export class WorkspaceConfigurationModel extends CustomConfigurationModel {
|
||||
export class WorkspaceSettingsModel extends ConfigurationModel {
|
||||
|
||||
private _raw: any;
|
||||
private _folders: IStoredWorkspaceFolder[];
|
||||
private _worksapaceSettings: WorkspaceSettingsModel;
|
||||
private _unsupportedKeys: string[];
|
||||
|
||||
public update(content: string): void {
|
||||
super.update(content);
|
||||
this._folders = (this._raw['folders'] || []) as IStoredWorkspaceFolder[];
|
||||
this._worksapaceSettings = new WorkspaceSettingsModel(this._raw['settings'] || {});
|
||||
constructor(contents: any, keys: string[], overrides: IOverrides[], unsupportedKeys: string[]) {
|
||||
super(contents, keys, overrides);
|
||||
this._unsupportedKeys = unsupportedKeys;
|
||||
}
|
||||
|
||||
public get unsupportedKeys(): string[] {
|
||||
return this._unsupportedKeys;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class WorkspaceConfigurationModelParser extends ConfigurationModelParser {
|
||||
|
||||
private _folders: IStoredWorkspaceFolder[] = [];
|
||||
private _workspaceSettingsModelParser: FolderSettingsModelParser;
|
||||
|
||||
constructor(name: string) {
|
||||
super(name);
|
||||
this._workspaceSettingsModelParser = new FolderSettingsModelParser(name);
|
||||
}
|
||||
|
||||
get folders(): IStoredWorkspaceFolder[] {
|
||||
return this._folders;
|
||||
}
|
||||
|
||||
get workspaceConfiguration(): ConfigurationModel {
|
||||
return this._worksapaceSettings || new WorkspaceSettingsModel({});
|
||||
}
|
||||
|
||||
get workspaceSettingsModel(): WorkspaceSettingsModel {
|
||||
return this._worksapaceSettings || new WorkspaceSettingsModel({});
|
||||
return this._workspaceSettingsModelParser.folderSettingsModel;
|
||||
}
|
||||
|
||||
protected processRaw(raw: any): void {
|
||||
this._raw = raw;
|
||||
super.processRaw(raw);
|
||||
reprocessWorkspaceSettings(): void {
|
||||
this._workspaceSettingsModelParser.reprocess();
|
||||
}
|
||||
|
||||
protected parseRaw(raw: any): IConfigurationModel {
|
||||
this._folders = (raw['folders'] || []) as IStoredWorkspaceFolder[];
|
||||
this._workspaceSettingsModelParser.parse(raw['settings']);
|
||||
return super.parseRaw(raw);
|
||||
}
|
||||
}
|
||||
|
||||
export class StandaloneConfigurationModelParser extends ConfigurationModelParser {
|
||||
|
||||
constructor(name: string, private readonly scope: string) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
protected parseRaw(raw: any): IConfigurationModel {
|
||||
const contents = toValuesTree(raw, message => console.error(`Conflict in settings file ${this._name}: ${message}`));
|
||||
const scopedContents = Object.create(null);
|
||||
scopedContents[this.scope] = contents;
|
||||
const keys = Object.keys(raw).map(key => `${this.scope}.${key}`);
|
||||
return { contents: scopedContents, keys, overrides: [] };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class WorkspaceSettingsModel extends ConfigurationModel {
|
||||
export class FolderSettingsModelParser extends ConfigurationModelParser {
|
||||
|
||||
private _raw: any;
|
||||
private _unsupportedKeys: string[];
|
||||
private _workspaceSettingsModel: WorkspaceSettingsModel;
|
||||
|
||||
constructor(raw: any) {
|
||||
super();
|
||||
this._raw = raw;
|
||||
this.update();
|
||||
constructor(name: string, private configurationScope?: ConfigurationScope) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public get unsupportedKeys(): string[] {
|
||||
return this._unsupportedKeys || [];
|
||||
parse(content: string | any): void {
|
||||
this._raw = typeof content === 'string' ? this.parseContent(content) : content;
|
||||
this.parseWorkspaceSettings(this._raw);
|
||||
}
|
||||
|
||||
update(): void {
|
||||
const { unsupportedKeys, contents } = processWorkspaceSettings(this._raw);
|
||||
this._unsupportedKeys = unsupportedKeys;
|
||||
this._contents = toValuesTree(contents, message => console.error(`Conflict in workspace settings file: ${message}`));
|
||||
this._keys = Object.keys(contents);
|
||||
}
|
||||
}
|
||||
|
||||
export class ScopedConfigurationModel extends CustomConfigurationModel {
|
||||
|
||||
constructor(content: string, name: string, public readonly scope: string) {
|
||||
super(null, name);
|
||||
this.update(content);
|
||||
get configurationModel(): ConfigurationModel {
|
||||
return this._workspaceSettingsModel || new WorkspaceSettingsModel({}, [], [], []);
|
||||
}
|
||||
|
||||
public update(content: string): void {
|
||||
super.update(content);
|
||||
const contents = Object.create(null);
|
||||
contents[this.scope] = this.contents;
|
||||
this._contents = contents;
|
||||
get folderSettingsModel(): WorkspaceSettingsModel {
|
||||
return <WorkspaceSettingsModel>this.configurationModel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function processWorkspaceSettings(content: any): { unsupportedKeys: string[], contents: any } {
|
||||
const isNotExecutable = (key: string, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema }): boolean => {
|
||||
const propertySchema = configurationProperties[key];
|
||||
if (!propertySchema) {
|
||||
return true; // Unknown propertis are ignored from checks
|
||||
}
|
||||
return !propertySchema.isExecutable;
|
||||
};
|
||||
|
||||
const unsupportedKeys = [];
|
||||
const contents = {};
|
||||
const configurationProperties = Registry.as<IConfigurationRegistry>(Extensions.Configuration).getConfigurationProperties();
|
||||
for (let key in content) {
|
||||
if (isNotExecutable(key, configurationProperties)) {
|
||||
contents[key] = content[key];
|
||||
} else {
|
||||
unsupportedKeys.push(key);
|
||||
}
|
||||
}
|
||||
return { contents, unsupportedKeys };
|
||||
}
|
||||
|
||||
export class FolderSettingsModel extends CustomConfigurationModel {
|
||||
|
||||
private _raw: any;
|
||||
private _unsupportedKeys: string[];
|
||||
|
||||
protected processRaw(raw: any): void {
|
||||
this._raw = raw;
|
||||
const { unsupportedKeys, contents } = processWorkspaceSettings(raw);
|
||||
this._unsupportedKeys = unsupportedKeys;
|
||||
return super.processRaw(contents);
|
||||
reprocess(): void {
|
||||
this.parse(this._raw);
|
||||
}
|
||||
|
||||
public reprocess(): void {
|
||||
this.processRaw(this._raw);
|
||||
}
|
||||
|
||||
public get unsupportedKeys(): string[] {
|
||||
return this._unsupportedKeys || [];
|
||||
}
|
||||
|
||||
public createWorkspaceConfigurationModel(): ConfigurationModel {
|
||||
return this.createScopedConfigurationModel(ConfigurationScope.WINDOW);
|
||||
}
|
||||
|
||||
public createFolderScopedConfigurationModel(): ConfigurationModel {
|
||||
return this.createScopedConfigurationModel(ConfigurationScope.RESOURCE);
|
||||
}
|
||||
|
||||
private createScopedConfigurationModel(scope: ConfigurationScope): ConfigurationModel {
|
||||
const workspaceRaw = {};
|
||||
private parseWorkspaceSettings(rawSettings: any): void {
|
||||
const unsupportedKeys = [];
|
||||
const rawWorkspaceSettings = {};
|
||||
const configurationProperties = Registry.as<IConfigurationRegistry>(Extensions.Configuration).getConfigurationProperties();
|
||||
for (let key in this._raw) {
|
||||
if (this.getScope(key, configurationProperties) === scope) {
|
||||
workspaceRaw[key] = this._raw[key];
|
||||
for (let key in rawSettings) {
|
||||
if (this.isNotExecutable(key, configurationProperties)) {
|
||||
if (this.configurationScope === void 0 || this.getScope(key, configurationProperties) === this.configurationScope) {
|
||||
rawWorkspaceSettings[key] = rawSettings[key];
|
||||
}
|
||||
} else {
|
||||
unsupportedKeys.push(key);
|
||||
}
|
||||
}
|
||||
const workspaceContents = toValuesTree(workspaceRaw, message => console.error(`Conflict in workspace settings file: ${message}`));
|
||||
const workspaceKeys = Object.keys(workspaceRaw);
|
||||
return new ConfigurationModel(workspaceContents, workspaceKeys, clone(this._overrides));
|
||||
const configurationModel = this.parseRaw(rawWorkspaceSettings);
|
||||
this._workspaceSettingsModel = new WorkspaceSettingsModel(configurationModel.contents, configurationModel.keys, configurationModel.overrides, unsupportedKeys);
|
||||
}
|
||||
|
||||
private getScope(key: string, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema }): ConfigurationScope {
|
||||
const propertySchema = configurationProperties[key];
|
||||
return propertySchema ? propertySchema.scope : ConfigurationScope.WINDOW;
|
||||
}
|
||||
}
|
||||
|
||||
export class FolderConfigurationModel extends CustomConfigurationModel {
|
||||
|
||||
constructor(public readonly workspaceSettingsConfig: FolderSettingsModel, private scopedConfigs: ScopedConfigurationModel[], private scope: ConfigurationScope) {
|
||||
super();
|
||||
this.consolidate();
|
||||
}
|
||||
|
||||
private consolidate(): void {
|
||||
this._contents = {};
|
||||
this._overrides = [];
|
||||
|
||||
this.doMerge(this, ConfigurationScope.WINDOW === this.scope ? this.workspaceSettingsConfig : this.workspaceSettingsConfig.createFolderScopedConfigurationModel());
|
||||
for (const configModel of this.scopedConfigs) {
|
||||
this.doMerge(this, configModel);
|
||||
private isNotExecutable(key: string, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema }): boolean {
|
||||
const propertySchema = configurationProperties[key];
|
||||
if (!propertySchema) {
|
||||
return true; // Unknown propertis are ignored from checks
|
||||
}
|
||||
}
|
||||
|
||||
public get keys(): string[] {
|
||||
const keys: string[] = [...this.workspaceSettingsConfig.keys];
|
||||
this.scopedConfigs.forEach(scopedConfigModel => {
|
||||
Object.keys(WORKSPACE_STANDALONE_CONFIGURATIONS).forEach(scope => {
|
||||
if (scopedConfigModel.scope === scope) {
|
||||
keys.push(...scopedConfigModel.keys.map(key => `${scope}.${key}`));
|
||||
}
|
||||
});
|
||||
});
|
||||
return keys;
|
||||
}
|
||||
|
||||
public update(): void {
|
||||
this.workspaceSettingsConfig.reprocess();
|
||||
this.consolidate();
|
||||
return !propertySchema.isExecutable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,22 +137,18 @@ export class Configuration extends BaseConfiguration {
|
||||
defaults: ConfigurationModel,
|
||||
user: ConfigurationModel,
|
||||
workspaceConfiguration: ConfigurationModel,
|
||||
protected folders: StrictResourceMap<FolderConfigurationModel>,
|
||||
folders: StrictResourceMap<ConfigurationModel>,
|
||||
memoryConfiguration: ConfigurationModel,
|
||||
memoryConfigurationByResource: StrictResourceMap<ConfigurationModel>,
|
||||
private readonly _workspace: Workspace) {
|
||||
super(defaults, user, workspaceConfiguration, folders, memoryConfiguration, memoryConfigurationByResource);
|
||||
}
|
||||
|
||||
getSection<C>(section: string = '', overrides: IConfigurationOverrides = {}): C {
|
||||
return super.getSection(section, overrides, this._workspace);
|
||||
}
|
||||
|
||||
getValue(key: string, overrides: IConfigurationOverrides = {}): any {
|
||||
return super.getValue(key, overrides, this._workspace);
|
||||
}
|
||||
|
||||
lookup<C>(key: string, overrides: IConfigurationOverrides = {}): {
|
||||
inspect<C>(key: string, overrides: IConfigurationOverrides = {}): {
|
||||
default: C,
|
||||
user: C,
|
||||
workspace: C,
|
||||
@@ -220,7 +156,7 @@ export class Configuration extends BaseConfiguration {
|
||||
memory?: C
|
||||
value: C,
|
||||
} {
|
||||
return super.lookup(key, overrides, this._workspace);
|
||||
return super.inspect(key, overrides, this._workspace);
|
||||
}
|
||||
|
||||
keys(): {
|
||||
@@ -232,103 +168,95 @@ export class Configuration extends BaseConfiguration {
|
||||
return super.keys(this._workspace);
|
||||
}
|
||||
|
||||
updateDefaultConfiguration(defaults: ConfigurationModel): void {
|
||||
this._defaults = defaults;
|
||||
this.merge();
|
||||
}
|
||||
|
||||
updateUserConfiguration(user: ConfigurationModel): ConfigurationChangeEvent {
|
||||
const { added, updated, removed } = compare(this._user, user);
|
||||
compareAndUpdateUserConfiguration(user: ConfigurationModel): ConfigurationChangeEvent {
|
||||
const { added, updated, removed } = compare(this.user, user);
|
||||
let changedKeys = [...added, ...updated, ...removed];
|
||||
if (changedKeys.length) {
|
||||
const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._memoryConfiguration, this._memoryConfigurationByResource, this._workspace);
|
||||
|
||||
this._user = user;
|
||||
this.merge();
|
||||
|
||||
changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue(key), this.getValue(key)));
|
||||
const oldValues = changedKeys.map(key => this.getValue(key));
|
||||
super.updateUserConfiguration(user);
|
||||
changedKeys = changedKeys.filter((key, index) => !equals(oldValues[index], this.getValue(key)));
|
||||
}
|
||||
return new ConfigurationChangeEvent().change(changedKeys);
|
||||
}
|
||||
|
||||
updateWorkspaceConfiguration(workspaceConfiguration: ConfigurationModel): ConfigurationChangeEvent {
|
||||
const { added, updated, removed } = compare(this._workspaceConfiguration, workspaceConfiguration);
|
||||
compareAndUpdateWorkspaceConfiguration(workspaceConfiguration: ConfigurationModel): ConfigurationChangeEvent {
|
||||
const { added, updated, removed } = compare(this.workspace, workspaceConfiguration);
|
||||
let changedKeys = [...added, ...updated, ...removed];
|
||||
if (changedKeys.length) {
|
||||
const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._memoryConfiguration, this._memoryConfigurationByResource, this._workspace);
|
||||
|
||||
this._workspaceConfiguration = workspaceConfiguration;
|
||||
this.merge();
|
||||
|
||||
changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue(key), this.getValue(key)));
|
||||
const oldValues = changedKeys.map(key => this.getValue(key));
|
||||
super.updateWorkspaceConfiguration(workspaceConfiguration);
|
||||
changedKeys = changedKeys.filter((key, index) => !equals(oldValues[index], this.getValue(key)));
|
||||
}
|
||||
return new ConfigurationChangeEvent().change(changedKeys);
|
||||
}
|
||||
|
||||
updateFolderConfiguration(resource: URI, configuration: FolderConfigurationModel): ConfigurationChangeEvent {
|
||||
compareAndUpdateFolderConfiguration(resource: URI, folderConfiguration: ConfigurationModel): ConfigurationChangeEvent {
|
||||
const currentFolderConfiguration = this.folders.get(resource);
|
||||
|
||||
if (currentFolderConfiguration) {
|
||||
const { added, updated, removed } = compare(currentFolderConfiguration, configuration);
|
||||
const { added, updated, removed } = compare(currentFolderConfiguration, folderConfiguration);
|
||||
let changedKeys = [...added, ...updated, ...removed];
|
||||
if (changedKeys.length) {
|
||||
const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._memoryConfiguration, this._memoryConfigurationByResource, this._workspace);
|
||||
|
||||
this.folders.set(resource, configuration);
|
||||
this.mergeFolder(resource);
|
||||
|
||||
changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue(key, { resource }), this.getValue(key, { resource })));
|
||||
const oldValues = changedKeys.map(key => this.getValue(key, { resource }));
|
||||
super.updateFolderConfiguration(resource, folderConfiguration);
|
||||
changedKeys = changedKeys.filter((key, index) => !equals(oldValues[index], this.getValue(key, { resource })));
|
||||
}
|
||||
return new ConfigurationChangeEvent().change(changedKeys, resource);
|
||||
} else {
|
||||
super.updateFolderConfiguration(resource, folderConfiguration);
|
||||
return new ConfigurationChangeEvent().change(folderConfiguration.keys, resource);
|
||||
}
|
||||
|
||||
this.folders.set(resource, configuration);
|
||||
this.mergeFolder(resource);
|
||||
return new ConfigurationChangeEvent().change(configuration.keys, resource);
|
||||
}
|
||||
|
||||
deleteFolderConfiguration(folder: URI): ConfigurationChangeEvent {
|
||||
compareAndDeleteFolderConfiguration(folder: URI): ConfigurationChangeEvent {
|
||||
if (this._workspace && this._workspace.folders.length > 0 && this._workspace.folders[0].uri.toString() === folder.toString()) {
|
||||
// Do not remove workspace configuration
|
||||
return new ConfigurationChangeEvent();
|
||||
}
|
||||
|
||||
const keys = this.folders.get(folder).keys;
|
||||
this.folders.delete(folder);
|
||||
this._foldersConsolidatedConfigurations.delete(folder);
|
||||
super.deleteFolderConfiguration(folder);
|
||||
return new ConfigurationChangeEvent().change(keys, folder);
|
||||
}
|
||||
|
||||
getFolderConfigurationModel(folder: URI): FolderConfigurationModel {
|
||||
return <FolderConfigurationModel>this.folders.get(folder);
|
||||
}
|
||||
|
||||
compare(other: Configuration): string[] {
|
||||
let from = other.allKeys();
|
||||
let to = this.allKeys();
|
||||
|
||||
const added = to.filter(key => from.indexOf(key) === -1);
|
||||
const removed = from.filter(key => to.indexOf(key) === -1);
|
||||
const updated = [];
|
||||
|
||||
for (const key of from) {
|
||||
const value1 = this.getValue(key);
|
||||
const value2 = other.getValue(key);
|
||||
if (!equals(value1, value2)) {
|
||||
updated.push(key);
|
||||
const result = [];
|
||||
for (const key of this.allKeys()) {
|
||||
if (!equals(this.getValue(key), other.getValue(key))
|
||||
|| (this._workspace && this._workspace.folders.some(folder => !equals(this.getValue(key, { resource: folder.uri }), other.getValue(key, { resource: folder.uri }))))) {
|
||||
result.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
return [...added, ...removed, ...updated];
|
||||
return result;
|
||||
}
|
||||
|
||||
allKeys(): string[] {
|
||||
let keys = this.keys();
|
||||
let all = [...keys.default, ...keys.user, ...keys.workspace];
|
||||
for (const resource of this.folders.keys()) {
|
||||
all.push(...this.folders.get(resource).keys);
|
||||
return super.allKeys(this._workspace);
|
||||
}
|
||||
}
|
||||
|
||||
export class AllKeysConfigurationChangeEvent extends AbstractConfigurationChangeEvent implements IConfigurationChangeEvent {
|
||||
|
||||
private _changedConfiguration: ConfigurationModel = null;
|
||||
|
||||
constructor(private _configuration: Configuration, readonly source: ConfigurationTarget, readonly sourceConfig: any) { super(); }
|
||||
|
||||
get changedConfiguration(): ConfigurationModel {
|
||||
if (!this._changedConfiguration) {
|
||||
this._changedConfiguration = new ConfigurationModel();
|
||||
this.updateKeys(this._changedConfiguration, this.affectedKeys);
|
||||
}
|
||||
return distinct(all);
|
||||
return this._changedConfiguration;
|
||||
}
|
||||
|
||||
get changedConfigurationByResource(): StrictResourceMap<IConfigurationModel> {
|
||||
return new StrictResourceMap();
|
||||
}
|
||||
|
||||
get affectedKeys(): string[] {
|
||||
return this._configuration.allKeys();
|
||||
}
|
||||
|
||||
affectsConfiguration(config: string, resource?: URI): boolean {
|
||||
return this.doesConfigurationContains(this.changedConfiguration, config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,13 +15,16 @@ import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { ConfigWatcher } from 'vs/base/node/config';
|
||||
import { CustomConfigurationModel, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { WorkspaceConfigurationModel, ScopedConfigurationModel, FolderConfigurationModel, FolderSettingsModel, WorkspaceSettingsModel } from 'vs/workbench/services/configuration/common/configurationModels';
|
||||
import { WORKSPACE_STANDALONE_CONFIGURATIONS, WORKSPACE_CONFIG_DEFAULT_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { ConfigurationModel, ConfigurationModelParser } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { WorkspaceConfigurationModelParser, FolderSettingsModelParser, StandaloneConfigurationModelParser, WorkspaceSettingsModel } from 'vs/workbench/services/configuration/common/configurationModels';
|
||||
import { WORKSPACE_STANDALONE_CONFIGURATIONS, FOLDER_SETTINGS_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { IStoredWorkspace, IStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces';
|
||||
import * as extfs from 'vs/base/node/extfs';
|
||||
import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService';
|
||||
import { WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { relative } from 'path';
|
||||
import { equals } from 'vs/base/common/objects';
|
||||
|
||||
// node.hs helper functions
|
||||
|
||||
@@ -73,7 +76,7 @@ function resolveStat(resource: URI): TPromise<IStat> {
|
||||
export class WorkspaceConfiguration extends Disposable {
|
||||
|
||||
private _workspaceConfigPath: URI;
|
||||
private _workspaceConfigurationWatcher: ConfigWatcher<WorkspaceConfigurationModel>;
|
||||
private _workspaceConfigurationWatcher: ConfigWatcher<WorkspaceConfigurationModelParser>;
|
||||
private _workspaceConfigurationWatcherDisposables: IDisposable[] = [];
|
||||
|
||||
private _onDidUpdateConfiguration: Emitter<void> = this._register(new Emitter<void>());
|
||||
@@ -88,12 +91,15 @@ export class WorkspaceConfiguration extends Disposable {
|
||||
|
||||
this.stopListeningToWatcher();
|
||||
return new TPromise<void>((c, e) => {
|
||||
const defaultConfig = new WorkspaceConfigurationModelParser(this._workspaceConfigPath.fsPath);
|
||||
defaultConfig.parse(JSON.stringify({ folders: [] } as IStoredWorkspace, null, '\t'));
|
||||
this._workspaceConfigurationWatcher = new ConfigWatcher(this._workspaceConfigPath.fsPath, {
|
||||
changeBufferDelay: 300,
|
||||
onError: error => errors.onUnexpectedError(error),
|
||||
defaultConfig: new WorkspaceConfigurationModel(JSON.stringify({ folders: [] } as IStoredWorkspace, null, '\t'), this._workspaceConfigPath.fsPath),
|
||||
defaultConfig,
|
||||
parse: (content: string, parseErrors: any[]) => {
|
||||
const workspaceConfigurationModel = new WorkspaceConfigurationModel(content, this._workspaceConfigPath.fsPath);
|
||||
const workspaceConfigurationModel = new WorkspaceConfigurationModelParser(this._workspaceConfigPath.fsPath);
|
||||
workspaceConfigurationModel.parse(content);
|
||||
parseErrors = [...workspaceConfigurationModel.errors];
|
||||
return workspaceConfigurationModel;
|
||||
}, initCallback: () => c(null)
|
||||
@@ -102,8 +108,8 @@ export class WorkspaceConfiguration extends Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
private get workspaceConfigurationModel(): WorkspaceConfigurationModel {
|
||||
return this._workspaceConfigurationWatcher ? this._workspaceConfigurationWatcher.getConfig() : new WorkspaceConfigurationModel();
|
||||
private get workspaceConfigurationModelParser(): WorkspaceConfigurationModelParser {
|
||||
return this._workspaceConfigurationWatcher ? this._workspaceConfigurationWatcher.getConfig() : new WorkspaceConfigurationModelParser(this._workspaceConfigPath ? this._workspaceConfigPath.fsPath : '');
|
||||
}
|
||||
|
||||
reload(): TPromise<void> {
|
||||
@@ -115,7 +121,7 @@ export class WorkspaceConfiguration extends Disposable {
|
||||
}
|
||||
|
||||
getFolders(): IStoredWorkspaceFolder[] {
|
||||
return this.workspaceConfigurationModel.folders;
|
||||
return this.workspaceConfigurationModelParser.folders;
|
||||
}
|
||||
|
||||
setFolders(folders: IStoredWorkspaceFolder[], jsonEditingService: JSONEditingService): TPromise<void> {
|
||||
@@ -124,11 +130,16 @@ export class WorkspaceConfiguration extends Disposable {
|
||||
}
|
||||
|
||||
getConfiguration(): ConfigurationModel {
|
||||
return this.workspaceConfigurationModel.workspaceConfiguration;
|
||||
return this.workspaceConfigurationModelParser.workspaceSettingsModel;
|
||||
}
|
||||
|
||||
getWorkspaceSettings(): WorkspaceSettingsModel {
|
||||
return this.workspaceConfigurationModel.workspaceSettingsModel;
|
||||
return this.workspaceConfigurationModelParser.workspaceSettingsModel;
|
||||
}
|
||||
|
||||
reprocessWorkspaceSettings(): ConfigurationModel {
|
||||
this.workspaceConfigurationModelParser.reprocessWorkspaceSettings();
|
||||
return this.getConfiguration();
|
||||
}
|
||||
|
||||
private listenToWatcher() {
|
||||
@@ -148,32 +159,54 @@ export class WorkspaceConfiguration extends Disposable {
|
||||
|
||||
export class FolderConfiguration extends Disposable {
|
||||
|
||||
private static RELOAD_CONFIGURATION_DELAY = 50;
|
||||
private static readonly RELOAD_CONFIGURATION_DELAY = 50;
|
||||
|
||||
private bulkFetchFromWorkspacePromise: TPromise;
|
||||
private workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: TPromise<ConfigurationModel> };
|
||||
private workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: TPromise<ConfigurationModelParser> };
|
||||
|
||||
private _folderSettingsModelParser: FolderSettingsModelParser;
|
||||
private _standAloneConfigurations: ConfigurationModel[] = [];
|
||||
private _cache: ConfigurationModel = new ConfigurationModel();
|
||||
|
||||
private reloadConfigurationScheduler: RunOnceScheduler;
|
||||
private reloadConfigurationEventEmitter: Emitter<FolderConfigurationModel> = new Emitter<FolderConfigurationModel>();
|
||||
private reloadConfigurationEventEmitter: Emitter<ConfigurationModel> = new Emitter<ConfigurationModel>();
|
||||
|
||||
constructor(private folder: URI, private configFolderRelativePath: string, private scope: ConfigurationScope) {
|
||||
constructor(private folder: URI, private configFolderRelativePath: string, workbenchState: WorkbenchState) {
|
||||
super();
|
||||
|
||||
this._folderSettingsModelParser = new FolderSettingsModelParser(FOLDER_SETTINGS_PATH, WorkbenchState.WORKSPACE === workbenchState ? ConfigurationScope.RESOURCE : void 0);
|
||||
this.workspaceFilePathToConfiguration = Object.create(null);
|
||||
this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.loadConfiguration().then(configuration => this.reloadConfigurationEventEmitter.fire(configuration), errors.onUnexpectedError), FolderConfiguration.RELOAD_CONFIGURATION_DELAY));
|
||||
}
|
||||
|
||||
loadConfiguration(): TPromise<FolderConfigurationModel> {
|
||||
loadConfiguration(): TPromise<ConfigurationModel> {
|
||||
// Load workspace locals
|
||||
return this.loadWorkspaceConfigFiles().then(workspaceConfigFiles => {
|
||||
this._standAloneConfigurations = Object.keys(workspaceConfigFiles).filter(key => key !== FOLDER_SETTINGS_PATH).map(key => <ConfigurationModel>workspaceConfigFiles[key].configurationModel);
|
||||
// Consolidate (support *.json files in the workspace settings folder)
|
||||
const workspaceSettingsConfig = <FolderSettingsModel>workspaceConfigFiles[WORKSPACE_CONFIG_DEFAULT_PATH] || new FolderSettingsModel(null);
|
||||
const otherConfigModels = Object.keys(workspaceConfigFiles).filter(key => key !== WORKSPACE_CONFIG_DEFAULT_PATH).map(key => <ScopedConfigurationModel>workspaceConfigFiles[key]);
|
||||
return new FolderConfigurationModel(workspaceSettingsConfig, otherConfigModels, this.scope);
|
||||
this.consolidate();
|
||||
return this._cache;
|
||||
});
|
||||
}
|
||||
|
||||
private loadWorkspaceConfigFiles(): TPromise<{ [relativeWorkspacePath: string]: ConfigurationModel }> {
|
||||
reprocess(): ConfigurationModel {
|
||||
const oldContents = this._folderSettingsModelParser.folderSettingsModel.contents;
|
||||
this._folderSettingsModelParser.reprocess();
|
||||
if (!equals(oldContents, this._folderSettingsModelParser.folderSettingsModel.contents)) {
|
||||
this.consolidate();
|
||||
}
|
||||
return this._cache;
|
||||
}
|
||||
|
||||
getUnsupportedKeys(): string[] {
|
||||
return this._folderSettingsModelParser.folderSettingsModel.unsupportedKeys;
|
||||
}
|
||||
|
||||
private consolidate(): void {
|
||||
this._cache = this._folderSettingsModelParser.folderSettingsModel.merge(...this._standAloneConfigurations);
|
||||
}
|
||||
|
||||
private loadWorkspaceConfigFiles(): TPromise<{ [relativeWorkspacePath: string]: ConfigurationModelParser }> {
|
||||
// once: when invoked for the first time we fetch json files that contribute settings
|
||||
if (!this.bulkFetchFromWorkspacePromise) {
|
||||
this.bulkFetchFromWorkspacePromise = resolveStat(this.toResource(this.configFolderRelativePath)).then(stat => {
|
||||
@@ -191,7 +224,7 @@ export class FolderConfiguration extends Disposable {
|
||||
}).map(stat => stat.resource));
|
||||
}, err => [] /* never fail this call */)
|
||||
.then((contents: IContent[]) => {
|
||||
contents.forEach(content => this.workspaceFilePathToConfiguration[this.toFolderRelativePath(content.resource)] = TPromise.as(this.createConfigModel(content)));
|
||||
contents.forEach(content => this.workspaceFilePathToConfiguration[this.toFolderRelativePath(content.resource)] = TPromise.as(this.createConfigurationModelParser(content)));
|
||||
}, errors.onUnexpectedError);
|
||||
}
|
||||
|
||||
@@ -200,7 +233,7 @@ export class FolderConfiguration extends Disposable {
|
||||
return this.bulkFetchFromWorkspacePromise.then(() => TPromise.join(this.workspaceFilePathToConfiguration));
|
||||
}
|
||||
|
||||
public handleWorkspaceFileEvents(event: FileChangesEvent): TPromise<FolderConfigurationModel> {
|
||||
public handleWorkspaceFileEvents(event: FileChangesEvent): TPromise<ConfigurationModel> {
|
||||
const events = event.changes;
|
||||
let affectedByChanges = false;
|
||||
|
||||
@@ -237,7 +270,7 @@ export class FolderConfiguration extends Disposable {
|
||||
break;
|
||||
case FileChangeType.UPDATED:
|
||||
case FileChangeType.ADDED:
|
||||
this.workspaceFilePathToConfiguration[workspacePath] = resolveContent(resource).then(content => this.createConfigModel(content), errors.onUnexpectedError);
|
||||
this.workspaceFilePathToConfiguration[workspacePath] = resolveContent(resource).then(content => this.createConfigurationModelParser(content), errors.onUnexpectedError);
|
||||
affectedByChanges = true;
|
||||
}
|
||||
}
|
||||
@@ -258,22 +291,24 @@ export class FolderConfiguration extends Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
private createConfigModel(content: IContent): ConfigurationModel {
|
||||
private createConfigurationModelParser(content: IContent): ConfigurationModelParser {
|
||||
const path = this.toFolderRelativePath(content.resource);
|
||||
if (path === WORKSPACE_CONFIG_DEFAULT_PATH) {
|
||||
return new FolderSettingsModel(content.value, content.resource.toString());
|
||||
if (path === FOLDER_SETTINGS_PATH) {
|
||||
this._folderSettingsModelParser.parse(content.value);
|
||||
return this._folderSettingsModelParser;
|
||||
} else {
|
||||
const matches = /\/([^\.]*)*\.json/.exec(path);
|
||||
if (matches && matches[1]) {
|
||||
return new ScopedConfigurationModel(content.value, content.resource.toString(), matches[1]);
|
||||
const standAloneConfigurationModelParser = new StandaloneConfigurationModelParser(content.resource.toString(), matches[1]);
|
||||
standAloneConfigurationModelParser.parse(content.value);
|
||||
return standAloneConfigurationModelParser;
|
||||
}
|
||||
}
|
||||
|
||||
return new CustomConfigurationModel(null);
|
||||
return new ConfigurationModelParser(null);
|
||||
}
|
||||
|
||||
private isWorkspaceConfigurationFile(folderRelativePath: string): boolean {
|
||||
return [WORKSPACE_CONFIG_DEFAULT_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS[TASKS_CONFIGURATION_KEY], WORKSPACE_STANDALONE_CONFIGURATIONS[LAUNCH_CONFIGURATION_KEY]].some(p => p === folderRelativePath);
|
||||
return [FOLDER_SETTINGS_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS[TASKS_CONFIGURATION_KEY], WORKSPACE_STANDALONE_CONFIGURATIONS[LAUNCH_CONFIGURATION_KEY]].some(p => p === folderRelativePath);
|
||||
}
|
||||
|
||||
private toResource(folderRelativePath: string): URI {
|
||||
@@ -286,7 +321,7 @@ export class FolderConfiguration extends Disposable {
|
||||
|
||||
private toFolderRelativePath(resource: URI, toOSPath?: boolean): string {
|
||||
if (this.contains(resource)) {
|
||||
return paths.normalize(paths.relative(this.folder.fsPath, resource.fsPath), toOSPath);
|
||||
return paths.normalize(relative(this.folder.fsPath, resource.fsPath), toOSPath);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -24,7 +24,7 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IConfigurationService, IConfigurationOverrides, keyFromOverrideIdentifier, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { WORKSPACE_CONFIG_DEFAULT_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { FOLDER_SETTINGS_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService';
|
||||
import { OVERRIDE_PROPERTY_PATTERN, IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
@@ -109,11 +109,6 @@ interface IConfigurationEditOperation extends IConfigurationValue {
|
||||
|
||||
}
|
||||
|
||||
interface IValidationResult {
|
||||
error?: ConfigurationEditingErrorCode;
|
||||
exists?: boolean;
|
||||
}
|
||||
|
||||
interface ConfigurationEditingOptions extends IConfigurationEditingOptions {
|
||||
force?: boolean;
|
||||
}
|
||||
@@ -161,7 +156,7 @@ export class ConfigurationEditingService {
|
||||
|
||||
private writeToBuffer(model: editorCommon.IModel, operation: IConfigurationEditOperation, save: boolean): TPromise<any> {
|
||||
const edit = this.getEdits(model, operation)[0];
|
||||
if (this.applyEditsToBuffer(edit, model) && save) {
|
||||
if (edit && this.applyEditsToBuffer(edit, model) && save) {
|
||||
return this.textFileService.save(operation.resource, { skipSaveParticipants: true /* programmatic change */ });
|
||||
}
|
||||
return TPromise.as(null);
|
||||
@@ -308,7 +303,7 @@ export class ConfigurationEditingService {
|
||||
return nls.localize('errorInvalidConfigurationFolder', "Unable to write into folder settings. Please open **Folder Settings** file under **{0}** folder to correct errors/warnings in it and try again.", workspaceFolderName);
|
||||
}
|
||||
return '';
|
||||
};
|
||||
}
|
||||
case ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY: {
|
||||
if (operation.workspaceStandAloneConfigurationKey === TASKS_CONFIGURATION_KEY) {
|
||||
return nls.localize('errorTasksConfigurationFileDirty', "Unable to write into tasks file because the file is dirty. Please save the **Tasks Configuration** file and try again.");
|
||||
@@ -326,7 +321,7 @@ export class ConfigurationEditingService {
|
||||
return nls.localize('errorConfigurationFileDirtyFolder', "Unable to write into folder settings because the file is dirty. Please save the **Folder Settings** file under **{0}** folder and try again.", workspaceFolderName);
|
||||
}
|
||||
return '';
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,7 +347,7 @@ export class ConfigurationEditingService {
|
||||
const content = JSON.stringify(value, null, insertSpaces ? strings.repeat(' ', tabSize) : '\t');
|
||||
return [{
|
||||
content,
|
||||
length: content.length,
|
||||
length: model.getValue().length,
|
||||
offset: 0
|
||||
}];
|
||||
}
|
||||
@@ -467,7 +462,7 @@ export class ConfigurationEditingService {
|
||||
return { key, jsonPath, value: config.value, resource: URI.file(this.environmentService.appSettingsPath), target };
|
||||
}
|
||||
|
||||
const resource = this.getConfigurationFileResource(target, WORKSPACE_CONFIG_DEFAULT_PATH, overrides.resource);
|
||||
const resource = this.getConfigurationFileResource(target, FOLDER_SETTINGS_PATH, overrides.resource);
|
||||
if (workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath) {
|
||||
jsonPath = ['settings', ...jsonPath];
|
||||
}
|
||||
|
||||
@@ -20,15 +20,14 @@ import { IWorkspaceContextService, Workspace, WorkbenchState, IWorkspaceFolder,
|
||||
import { FileChangesEvent } from 'vs/platform/files/common/files';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ConfigurationModel, ConfigurationChangeEvent, AllKeysConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { ConfigurationChangeEvent, ConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier, isConfigurationOverrides, IConfigurationData } from 'vs/platform/configuration/common/configuration';
|
||||
import { FolderConfigurationModel, Configuration, WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels';
|
||||
import { IWorkspaceConfigurationService, WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { ConfigurationService as GlobalConfigurationService } from 'vs/platform/configuration/node/configurationService';
|
||||
import { Configuration, WorkspaceConfigurationChangeEvent, AllKeysConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels';
|
||||
import { IWorkspaceConfigurationService, FOLDER_CONFIG_FOLDER_NAME, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IConfigurationNode, IConfigurationRegistry, Extensions, ConfigurationScope, settingsSchema, resourceSettingsSchema } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IConfigurationNode, IConfigurationRegistry, Extensions, settingsSchema, resourceSettingsSchema, IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { createHash } from 'crypto';
|
||||
import { getWorkspaceLabel, IWorkspacesService, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { getWorkspaceLabel, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
|
||||
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
@@ -40,6 +39,8 @@ import { JSONEditingService } from 'vs/workbench/services/configuration/node/jso
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { massageFolderPathForWorkspace } from 'vs/platform/workspaces/node/workspaces';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
import { UserConfiguration } from 'vs/platform/configuration/node/configuration';
|
||||
import { getBaseLabel } from 'vs/base/common/labels';
|
||||
|
||||
export class WorkspaceService extends Disposable implements IWorkspaceConfigurationService, IWorkspaceContextService {
|
||||
|
||||
@@ -47,7 +48,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
|
||||
private workspace: Workspace;
|
||||
private _configuration: Configuration;
|
||||
private baseConfigurationService: GlobalConfigurationService;
|
||||
private defaultConfiguration: DefaultConfigurationModel;
|
||||
private userConfiguration: UserConfiguration;
|
||||
private workspaceConfiguration: WorkspaceConfiguration;
|
||||
private cachedFolderConfigs: StrictResourceMap<FolderConfiguration>;
|
||||
|
||||
@@ -68,15 +70,17 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
private configurationEditingService: ConfigurationEditingService;
|
||||
private jsonEditingService: JSONEditingService;
|
||||
|
||||
constructor(private environmentService: IEnvironmentService, private workspacesService: IWorkspacesService, private workspaceSettingsRootFolder: string = WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME) {
|
||||
constructor(private environmentService: IEnvironmentService, private workspaceSettingsRootFolder: string = FOLDER_CONFIG_FOLDER_NAME) {
|
||||
super();
|
||||
|
||||
this.defaultConfiguration = new DefaultConfigurationModel();
|
||||
this.userConfiguration = this._register(new UserConfiguration(environmentService.appSettingsPath));
|
||||
this.workspaceConfiguration = this._register(new WorkspaceConfiguration());
|
||||
this._register(this.userConfiguration.onDidChangeConfiguration(() => this.onUserConfigurationChanged()));
|
||||
this._register(this.workspaceConfiguration.onDidUpdateConfiguration(() => this.onWorkspaceConfigurationChanged()));
|
||||
|
||||
this.baseConfigurationService = this._register(new GlobalConfigurationService(environmentService));
|
||||
this._register(this.baseConfigurationService.onDidChangeConfiguration(e => this.onBaseConfigurationChanged(e)));
|
||||
this._register(Registry.as<IConfigurationRegistry>(Extensions.Configuration).onDidRegisterConfiguration(e => this.registerConfigurationSchemas()));
|
||||
this._register(Registry.as<IConfigurationRegistry>(Extensions.Configuration).onDidRegisterConfiguration(configurationProperties => this.onDefaultConfigurationChanged(configurationProperties)));
|
||||
|
||||
this.workspaceEditingQueue = new Queue<void>();
|
||||
}
|
||||
@@ -222,25 +226,21 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
return this._configuration.toData();
|
||||
}
|
||||
|
||||
getConfiguration<T>(): T
|
||||
getConfiguration<T>(section: string): T
|
||||
getConfiguration<T>(overrides: IConfigurationOverrides): T
|
||||
getConfiguration<T>(section: string, overrides: IConfigurationOverrides): T
|
||||
getConfiguration(arg1?: any, arg2?: any): any {
|
||||
getValue<T>(): T;
|
||||
getValue<T>(section: string): T;
|
||||
getValue<T>(overrides: IConfigurationOverrides): T;
|
||||
getValue<T>(section: string, overrides: IConfigurationOverrides): T;
|
||||
getValue(arg1?: any, arg2?: any): any {
|
||||
const section = typeof arg1 === 'string' ? arg1 : void 0;
|
||||
const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : void 0;
|
||||
return this._configuration.getSection(section, overrides);
|
||||
return this._configuration.getValue(section, overrides);
|
||||
}
|
||||
|
||||
getValue<T>(key: string, overrides?: IConfigurationOverrides): T {
|
||||
return this._configuration.getValue(key, overrides);
|
||||
}
|
||||
|
||||
updateValue(key: string, value: any): TPromise<void>
|
||||
updateValue(key: string, value: any, overrides: IConfigurationOverrides): TPromise<void>
|
||||
updateValue(key: string, value: any, target: ConfigurationTarget): TPromise<void>
|
||||
updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): TPromise<void>
|
||||
updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget, donotNotifyError: boolean): TPromise<void>
|
||||
updateValue(key: string, value: any): TPromise<void>;
|
||||
updateValue(key: string, value: any, overrides: IConfigurationOverrides): TPromise<void>;
|
||||
updateValue(key: string, value: any, target: ConfigurationTarget): TPromise<void>;
|
||||
updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): TPromise<void>;
|
||||
updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget, donotNotifyError: boolean): TPromise<void>;
|
||||
updateValue(key: string, value: any, arg3?: any, arg4?: any, donotNotifyError?: any): TPromise<void> {
|
||||
assert.ok(this.configurationEditingService, 'Workbench is not initialized yet');
|
||||
const overrides = isConfigurationOverrides(arg3) ? arg3 : void 0;
|
||||
@@ -266,7 +266,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
memory?: T,
|
||||
value: T
|
||||
} {
|
||||
return this._configuration.lookup<T>(key);
|
||||
return this._configuration.inspect<T>(key, overrides);
|
||||
}
|
||||
|
||||
keys(): {
|
||||
@@ -281,7 +281,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
getUnsupportedWorkspaceKeys(): string[] {
|
||||
const unsupportedWorkspaceKeys = [...this.workspaceConfiguration.getWorkspaceSettings().unsupportedKeys];
|
||||
for (const folder of this.workspace.folders) {
|
||||
unsupportedWorkspaceKeys.push(...this._configuration.getFolderConfigurationModel(folder.uri).workspaceSettingsConfig.unsupportedKeys);
|
||||
unsupportedWorkspaceKeys.push(...this.cachedFolderConfigs.get(folder.uri).getUnsupportedKeys());
|
||||
}
|
||||
return distinct(unsupportedWorkspaceKeys);
|
||||
}
|
||||
@@ -336,7 +336,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
const ctime = isLinux ? workspaceStat.ino : workspaceStat.birthtime.getTime(); // On Linux, birthtime is ctime, so we cannot use it! We use the ino instead!
|
||||
const id = createHash('md5').update(folderPath.fsPath).update(ctime ? String(ctime) : '').digest('hex');
|
||||
const folder = URI.file(folderPath.fsPath);
|
||||
return new Workspace(id, paths.basename(folderPath.fsPath), toWorkspaceFolders([{ path: folder.fsPath }]), null, ctime);
|
||||
return new Workspace(id, getBaseLabel(folder), toWorkspaceFolders([{ path: folder.fsPath }]), null, ctime);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -346,34 +346,37 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
}
|
||||
|
||||
private updateWorkspaceAndInitializeConfiguration(workspace: Workspace): TPromise<void> {
|
||||
let folderChanges: IWorkspaceFoldersChangeEvent;
|
||||
if (this.workspace) {
|
||||
const currentState = this.getWorkbenchState();
|
||||
const currentWorkspacePath = this.workspace.configuration ? this.workspace.configuration.fsPath : void 0;
|
||||
const currentFolders = this.workspace.folders;
|
||||
const hasWorkspaceBefore = !!this.workspace;
|
||||
let previousState;
|
||||
let previousWorkspacePath;
|
||||
let previousFolders;
|
||||
|
||||
if (hasWorkspaceBefore) {
|
||||
previousState = this.getWorkbenchState();
|
||||
previousWorkspacePath = this.workspace.configuration ? this.workspace.configuration.fsPath : void 0;
|
||||
previousFolders = this.workspace.folders;
|
||||
this.workspace.update(workspace);
|
||||
|
||||
const newState = this.getWorkbenchState();
|
||||
if (newState !== currentState) {
|
||||
this._onDidChangeWorkbenchState.fire(newState);
|
||||
}
|
||||
|
||||
const newWorkspacePath = this.workspace.configuration ? this.workspace.configuration.fsPath : void 0;
|
||||
if (newWorkspacePath !== currentWorkspacePath || newState !== currentState) {
|
||||
this._onDidChangeWorkspaceName.fire();
|
||||
}
|
||||
|
||||
folderChanges = this.compareFolders(currentFolders, this.workspace.folders);
|
||||
|
||||
} else {
|
||||
this.workspace = workspace;
|
||||
}
|
||||
|
||||
return this.initializeConfiguration().then(() => {
|
||||
// Trigger folders change after configuration initialization so that configuration is up to date.
|
||||
if (folderChanges && (folderChanges.added.length || folderChanges.removed.length || folderChanges.changed.length)) {
|
||||
this._onDidChangeWorkspaceFolders.fire(folderChanges);
|
||||
// Trigger changes after configuration initialization so that configuration is up to date.
|
||||
if (hasWorkspaceBefore) {
|
||||
const newState = this.getWorkbenchState();
|
||||
if (previousState && newState !== previousState) {
|
||||
this._onDidChangeWorkbenchState.fire(newState);
|
||||
}
|
||||
|
||||
const newWorkspacePath = this.workspace.configuration ? this.workspace.configuration.fsPath : void 0;
|
||||
if (previousWorkspacePath && newWorkspacePath !== previousWorkspacePath || newState !== previousState) {
|
||||
this._onDidChangeWorkspaceName.fire();
|
||||
}
|
||||
|
||||
const folderChanges = this.compareFolders(previousFolders, this.workspace.folders);
|
||||
if (folderChanges && (folderChanges.added.length || folderChanges.removed.length || folderChanges.changed.length)) {
|
||||
this._onDidChangeWorkspaceFolders.fire(folderChanges);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -402,7 +405,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
}
|
||||
|
||||
private reloadUserConfiguration(key?: string): TPromise<void> {
|
||||
return this.baseConfigurationService.reloadConfiguration();
|
||||
return this.userConfiguration.reload();
|
||||
}
|
||||
|
||||
private reloadWorkspaceConfiguration(key?: string): TPromise<void> {
|
||||
@@ -429,22 +432,22 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
.then((folderConfigurations) => {
|
||||
|
||||
let workspaceConfiguration = this.getWorkspaceConfigurationModel(folderConfigurations);
|
||||
const folderConfigurationModels = new StrictResourceMap<FolderConfigurationModel>();
|
||||
const folderConfigurationModels = new StrictResourceMap<ConfigurationModel>();
|
||||
folderConfigurations.forEach((folderConfiguration, index) => folderConfigurationModels.set(folders[index].uri, folderConfiguration));
|
||||
|
||||
const currentConfiguration = this._configuration;
|
||||
this._configuration = new Configuration(this.baseConfigurationService.configuration.defaults, this.baseConfigurationService.configuration.user, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new StrictResourceMap<ConfigurationModel>(), this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: Sandy Avoid passing null
|
||||
this._configuration = new Configuration(this.defaultConfiguration, this.userConfiguration.configurationModel, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new StrictResourceMap<ConfigurationModel>(), this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: Sandy Avoid passing null
|
||||
|
||||
if (currentConfiguration) {
|
||||
const changedKeys = this._configuration.compare(currentConfiguration);
|
||||
this.triggerConfigurationChange(new ConfigurationChangeEvent().change(changedKeys), ConfigurationTarget.WORKSPACE);
|
||||
} else {
|
||||
this._onDidChangeConfiguration.fire(new AllKeysConfigurationChangeEvent(this._configuration.allKeys(), ConfigurationTarget.WORKSPACE, this.getTargetConfiguration(ConfigurationTarget.WORKSPACE)));
|
||||
this._onDidChangeConfiguration.fire(new AllKeysConfigurationChangeEvent(this._configuration, ConfigurationTarget.WORKSPACE, this.getTargetConfiguration(ConfigurationTarget.WORKSPACE)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getWorkspaceConfigurationModel(folderConfigurations: FolderConfigurationModel[]): ConfigurationModel {
|
||||
private getWorkspaceConfigurationModel(folderConfigurations: ConfigurationModel[]): ConfigurationModel {
|
||||
switch (this.getWorkbenchState()) {
|
||||
case WorkbenchState.FOLDER:
|
||||
return folderConfigurations[0];
|
||||
@@ -455,6 +458,21 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
}
|
||||
}
|
||||
|
||||
private onDefaultConfigurationChanged(keys: string[]): void {
|
||||
this.defaultConfiguration = new DefaultConfigurationModel();
|
||||
this.registerConfigurationSchemas();
|
||||
if (this.workspace && this._configuration) {
|
||||
this._configuration.updateDefaultConfiguration(this.defaultConfiguration);
|
||||
if (this.getWorkbenchState() === WorkbenchState.FOLDER) {
|
||||
this._configuration.updateWorkspaceConfiguration(this.cachedFolderConfigs.get(this.workspace.folders[0].uri).reprocess());
|
||||
} else {
|
||||
this._configuration.updateWorkspaceConfiguration(this.workspaceConfiguration.reprocessWorkspaceSettings());
|
||||
this.workspace.folders.forEach(folder => this._configuration.updateFolderConfiguration(folder.uri, this.cachedFolderConfigs.get(folder.uri).reprocess()));
|
||||
}
|
||||
this.triggerConfigurationChange(new ConfigurationChangeEvent().change(keys), ConfigurationTarget.DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
private registerConfigurationSchemas(): void {
|
||||
if (this.workspace) {
|
||||
const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
|
||||
@@ -471,23 +489,14 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
}
|
||||
}
|
||||
|
||||
private onBaseConfigurationChanged(e: IConfigurationChangeEvent): void {
|
||||
if (this.workspace && this._configuration) {
|
||||
if (e.source === ConfigurationTarget.DEFAULT) {
|
||||
this.workspaceConfiguration.getWorkspaceSettings().update();
|
||||
this.workspace.folders.forEach(folder => this._configuration.getFolderConfigurationModel(folder.uri).update());
|
||||
this._configuration.updateDefaultConfiguration(this.baseConfigurationService.configuration.defaults);
|
||||
this.triggerConfigurationChange(new ConfigurationChangeEvent().change(e.affectedKeys), e.source);
|
||||
} else {
|
||||
let keys = this._configuration.updateUserConfiguration(this.baseConfigurationService.configuration.user);
|
||||
this.triggerConfigurationChange(keys, e.source);
|
||||
}
|
||||
}
|
||||
private onUserConfigurationChanged(): void {
|
||||
let keys = this._configuration.compareAndUpdateUserConfiguration(this.userConfiguration.configurationModel);
|
||||
this.triggerConfigurationChange(keys, ConfigurationTarget.USER);
|
||||
}
|
||||
|
||||
private onWorkspaceConfigurationChanged(): TPromise<void> {
|
||||
if (this.workspace && this.workspace.configuration && this._configuration) {
|
||||
const workspaceConfigurationChangeEvent = this._configuration.updateWorkspaceConfiguration(this.workspaceConfiguration.getConfiguration());
|
||||
const workspaceConfigurationChangeEvent = this._configuration.compareAndUpdateWorkspaceConfiguration(this.workspaceConfiguration.getConfiguration());
|
||||
let configuredFolders = toWorkspaceFolders(this.workspaceConfiguration.getFolders(), URI.file(paths.dirname(this.workspace.configuration.fsPath)));
|
||||
const changes = this.compareFolders(this.workspace.folders, configuredFolders);
|
||||
if (changes.added.length || changes.removed.length || changes.changed.length) {
|
||||
@@ -509,7 +518,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
// handle file event for each folder
|
||||
this.cachedFolderConfigs.get(folder.uri).handleWorkspaceFileEvents(event)
|
||||
// Update folder configuration if handled
|
||||
.then(folderConfiguration => folderConfiguration ? this._configuration.updateFolderConfiguration(folder.uri, folderConfiguration) : new ConfigurationChangeEvent()))
|
||||
.then(folderConfiguration => folderConfiguration ? this._configuration.compareAndUpdateFolderConfiguration(folder.uri, folderConfiguration) : new ConfigurationChangeEvent()))
|
||||
).then(changeEvents => {
|
||||
const consolidateChangeEvent = changeEvents.reduce((consolidated, e) => consolidated.change(e), new ConfigurationChangeEvent());
|
||||
this.triggerConfigurationChange(consolidateChangeEvent, ConfigurationTarget.WORKSPACE_FOLDER);
|
||||
@@ -522,8 +531,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
.then(folderConfiguration => {
|
||||
if (folderConfiguration) {
|
||||
// File change handled
|
||||
this._configuration.updateFolderConfiguration(folder.uri, folderConfiguration);
|
||||
const workspaceChangedKeys = this._configuration.updateWorkspaceConfiguration(folderConfiguration);
|
||||
this._configuration.compareAndUpdateFolderConfiguration(folder.uri, folderConfiguration);
|
||||
const workspaceChangedKeys = this._configuration.compareAndUpdateWorkspaceConfiguration(folderConfiguration);
|
||||
this.triggerConfigurationChange(workspaceChangedKeys, ConfigurationTarget.WORKSPACE);
|
||||
}
|
||||
});
|
||||
@@ -533,9 +542,9 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
this.disposeFolderConfiguration(folder);
|
||||
return this.loadFolderConfigurations([folder])
|
||||
.then(([folderConfiguration]) => {
|
||||
const folderChangedKeys = this._configuration.updateFolderConfiguration(folder.uri, folderConfiguration);
|
||||
const folderChangedKeys = this._configuration.compareAndUpdateFolderConfiguration(folder.uri, folderConfiguration);
|
||||
if (this.getWorkbenchState() === WorkbenchState.FOLDER) {
|
||||
const workspaceChangedKeys = this._configuration.updateWorkspaceConfiguration(folderConfiguration);
|
||||
const workspaceChangedKeys = this._configuration.compareAndUpdateWorkspaceConfiguration(folderConfiguration);
|
||||
this.triggerConfigurationChange(workspaceChangedKeys, ConfigurationTarget.WORKSPACE);
|
||||
} else {
|
||||
this.triggerConfigurationChange(folderChangedKeys, ConfigurationTarget.WORKSPACE_FOLDER);
|
||||
@@ -550,7 +559,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
for (const key of this.cachedFolderConfigs.keys()) {
|
||||
if (!this.workspace.folders.filter(folder => folder.uri.toString() === key.toString())[0]) {
|
||||
this.cachedFolderConfigs.delete(key);
|
||||
changeEvent = changeEvent.change(this._configuration.deleteFolderConfiguration(key));
|
||||
changeEvent = changeEvent.change(this._configuration.compareAndDeleteFolderConfiguration(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,7 +568,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
return this.loadFolderConfigurations(toInitialize)
|
||||
.then(folderConfigurations => {
|
||||
folderConfigurations.forEach((folderConfiguration, index) => {
|
||||
changeEvent = changeEvent.change(this._configuration.updateFolderConfiguration(toInitialize[index].uri, folderConfiguration));
|
||||
changeEvent = changeEvent.change(this._configuration.compareAndUpdateFolderConfiguration(toInitialize[index].uri, folderConfiguration));
|
||||
});
|
||||
return changeEvent;
|
||||
});
|
||||
@@ -567,9 +576,9 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
return TPromise.as(changeEvent);
|
||||
}
|
||||
|
||||
private loadFolderConfigurations(folders: IWorkspaceFolder[]): TPromise<FolderConfigurationModel[]> {
|
||||
private loadFolderConfigurations(folders: IWorkspaceFolder[]): TPromise<ConfigurationModel[]> {
|
||||
return TPromise.join([...folders.map(folder => {
|
||||
const folderConfiguration = new FolderConfiguration(folder.uri, this.workspaceSettingsRootFolder, this.getWorkbenchState() === WorkbenchState.WORKSPACE ? ConfigurationScope.RESOURCE : ConfigurationScope.WINDOW);
|
||||
const folderConfiguration = new FolderConfiguration(folder.uri, this.workspaceSettingsRootFolder, this.getWorkbenchState());
|
||||
this.cachedFolderConfigs.set(folder.uri, this._register(folderConfiguration));
|
||||
return folderConfiguration.loadConfiguration();
|
||||
})]);
|
||||
@@ -694,7 +703,7 @@ export class DefaultConfigurationExportHelper {
|
||||
}
|
||||
|
||||
private writeConfigModelAndQuit(targetPath: string): TPromise<void> {
|
||||
return this.extensionService.onReady()
|
||||
return this.extensionService.whenInstalledExtensionsRegistered()
|
||||
.then(() => this.writeConfigModel(targetPath))
|
||||
.then(() => this.commandService.executeCommand('workbench.action.quit'))
|
||||
.then(() => { });
|
||||
@@ -708,28 +717,33 @@ export class DefaultConfigurationExportHelper {
|
||||
}
|
||||
|
||||
private getConfigModel(): IConfigurationExport {
|
||||
const configurations = Registry.as<IConfigurationRegistry>(Extensions.Configuration).getConfigurations().slice();
|
||||
const configRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
|
||||
const configurations = configRegistry.getConfigurations().slice();
|
||||
const settings: IExportedConfigurationNode[] = [];
|
||||
|
||||
const processProperty = (name: string, prop: IConfigurationPropertySchema) => {
|
||||
const propDetails: IExportedConfigurationNode = {
|
||||
name,
|
||||
description: prop.description,
|
||||
default: prop.default,
|
||||
type: prop.type
|
||||
};
|
||||
|
||||
if (prop.enum) {
|
||||
propDetails.enum = prop.enum;
|
||||
}
|
||||
|
||||
if (prop.enumDescriptions) {
|
||||
propDetails.enumDescriptions = prop.enumDescriptions;
|
||||
}
|
||||
|
||||
settings.push(propDetails);
|
||||
};
|
||||
|
||||
const processConfig = (config: IConfigurationNode) => {
|
||||
if (config.properties) {
|
||||
for (let name in config.properties) {
|
||||
const prop = config.properties[name];
|
||||
const propDetails: IExportedConfigurationNode = {
|
||||
name,
|
||||
description: prop.description,
|
||||
default: prop.default,
|
||||
type: prop.type
|
||||
};
|
||||
|
||||
if (prop.enum) {
|
||||
propDetails.enum = prop.enum;
|
||||
}
|
||||
|
||||
if (prop.enumDescriptions) {
|
||||
propDetails.enumDescriptions = prop.enumDescriptions;
|
||||
}
|
||||
|
||||
settings.push(propDetails);
|
||||
processProperty(name, config.properties[name]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -740,6 +754,11 @@ export class DefaultConfigurationExportHelper {
|
||||
|
||||
configurations.forEach(processConfig);
|
||||
|
||||
const excludedProps = configRegistry.getExcludedConfigurationProperties();
|
||||
for (let name in excludedProps) {
|
||||
processProperty(name, excludedProps[name]);
|
||||
}
|
||||
|
||||
const result: IConfigurationExport = {
|
||||
settings: settings.sort((a, b) => a.name.localeCompare(b.name)),
|
||||
buildTime: Date.now(),
|
||||
|
||||
@@ -126,10 +126,10 @@ export class JSONEditingService implements IJSONEditingService {
|
||||
// User issues
|
||||
case JSONEditingErrorCode.ERROR_INVALID_FILE: {
|
||||
return nls.localize('errorInvalidFile', "Unable to write into the file. Please open the file to correct errors/warnings in the file and try again.");
|
||||
};
|
||||
}
|
||||
case JSONEditingErrorCode.ERROR_FILE_DIRTY: {
|
||||
return nls.localize('errorFileDirty', "Unable to write into the file because the file is dirty. Please save the file and try again.");
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,99 +6,93 @@
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { join } from 'vs/base/common/paths';
|
||||
import { FolderConfigurationModel, ScopedConfigurationModel, FolderSettingsModel, WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { FolderSettingsModelParser, WorkspaceConfigurationChangeEvent, StandaloneConfigurationModelParser, AllKeysConfigurationChangeEvent, Configuration } from 'vs/workbench/services/configuration/common/configurationModels';
|
||||
import { Workspace, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { ConfigurationChangeEvent, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { StrictResourceMap } from 'vs/base/common/map';
|
||||
|
||||
suite('ConfigurationService - Model', () => {
|
||||
suite('FolderSettingsModelParser', () => {
|
||||
|
||||
test('Test scoped configs are undefined', () => {
|
||||
const settingsConfig = new FolderSettingsModel(JSON.stringify({
|
||||
awesome: true
|
||||
}));
|
||||
|
||||
const testObject = new FolderConfigurationModel(settingsConfig, [], ConfigurationScope.WINDOW);
|
||||
|
||||
assert.equal(testObject.getSectionContents('task'), undefined);
|
||||
suiteSetup(() => {
|
||||
const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': 'FolderSettingsModelParser_1',
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'FolderSettingsModelParser.window': {
|
||||
'type': 'string',
|
||||
'default': 'isSet'
|
||||
},
|
||||
'FolderSettingsModelParser.resource': {
|
||||
'type': 'string',
|
||||
'default': 'isSet',
|
||||
scope: ConfigurationScope.RESOURCE
|
||||
},
|
||||
'FolderSettingsModelParser.executable': {
|
||||
'type': 'string',
|
||||
'default': 'isSet',
|
||||
isExecutable: true
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('Test consolidate (settings and tasks)', () => {
|
||||
const settingsConfig = new FolderSettingsModel(JSON.stringify({
|
||||
awesome: true
|
||||
}));
|
||||
test('parse all folder settings', () => {
|
||||
const testObject = new FolderSettingsModelParser('settings');
|
||||
|
||||
const tasksConfig = new ScopedConfigurationModel(JSON.stringify({
|
||||
awesome: false
|
||||
}), '', 'tasks');
|
||||
testObject.parse(JSON.stringify({ 'FolderSettingsModelParser.window': 'window', 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.executable': 'executable' }));
|
||||
|
||||
const expected = {
|
||||
awesome: true,
|
||||
tasks: {
|
||||
awesome: false
|
||||
}
|
||||
};
|
||||
|
||||
assert.deepEqual(new FolderConfigurationModel(settingsConfig, [tasksConfig], ConfigurationScope.WINDOW).contents, expected);
|
||||
assert.deepEqual(testObject.configurationModel.contents, { 'FolderSettingsModelParser': { 'window': 'window', 'resource': 'resource' } });
|
||||
});
|
||||
|
||||
test('Test consolidate (settings and launch)', () => {
|
||||
const settingsConfig = new FolderSettingsModel(JSON.stringify({
|
||||
awesome: true
|
||||
}));
|
||||
test('parse resource folder settings', () => {
|
||||
const testObject = new FolderSettingsModelParser('settings', ConfigurationScope.RESOURCE);
|
||||
|
||||
const launchConfig = new ScopedConfigurationModel(JSON.stringify({
|
||||
awesome: false
|
||||
}), '', 'launch');
|
||||
testObject.parse(JSON.stringify({ 'FolderSettingsModelParser.window': 'window', 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.executable': 'executable' }));
|
||||
|
||||
const expected = {
|
||||
awesome: true,
|
||||
launch: {
|
||||
awesome: false
|
||||
}
|
||||
};
|
||||
|
||||
assert.deepEqual(new FolderConfigurationModel(settingsConfig, [launchConfig], ConfigurationScope.WINDOW).contents, expected);
|
||||
assert.deepEqual(testObject.configurationModel.contents, { 'FolderSettingsModelParser': { 'resource': 'resource' } });
|
||||
});
|
||||
|
||||
test('Test consolidate (settings and launch and tasks) - launch/tasks wins over settings file', () => {
|
||||
const settingsConfig = new FolderSettingsModel(JSON.stringify({
|
||||
awesome: true,
|
||||
launch: {
|
||||
launchConfig: 'defined',
|
||||
otherLaunchConfig: 'alsoDefined'
|
||||
},
|
||||
tasks: {
|
||||
taskConfig: 'defined',
|
||||
otherTaskConfig: 'alsoDefined'
|
||||
test('reprocess folder settings excludes executable', () => {
|
||||
const testObject = new FolderSettingsModelParser('settings');
|
||||
|
||||
testObject.parse(JSON.stringify({ 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.anotherExecutable': 'executable' }));
|
||||
|
||||
assert.deepEqual(testObject.configurationModel.contents, { 'FolderSettingsModelParser': { 'resource': 'resource', 'anotherExecutable': 'executable' } });
|
||||
|
||||
const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': 'FolderSettingsModelParser_2',
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'FolderSettingsModelParser.anotherExecutable': {
|
||||
'type': 'string',
|
||||
'default': 'isSet',
|
||||
isExecutable: true
|
||||
}
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
const tasksConfig = new ScopedConfigurationModel(JSON.stringify({
|
||||
taskConfig: 'overwritten',
|
||||
}), '', 'tasks');
|
||||
|
||||
const launchConfig = new ScopedConfigurationModel(JSON.stringify({
|
||||
launchConfig: 'overwritten',
|
||||
}), '', 'launch');
|
||||
|
||||
const expected = {
|
||||
awesome: true,
|
||||
launch: {
|
||||
launchConfig: 'overwritten',
|
||||
otherLaunchConfig: 'alsoDefined'
|
||||
},
|
||||
tasks: {
|
||||
taskConfig: 'overwritten',
|
||||
otherTaskConfig: 'alsoDefined'
|
||||
}
|
||||
};
|
||||
|
||||
assert.deepEqual(new FolderConfigurationModel(settingsConfig, [launchConfig, tasksConfig], ConfigurationScope.WINDOW).contents, expected);
|
||||
assert.deepEqual(new FolderConfigurationModel(settingsConfig, [tasksConfig, launchConfig], ConfigurationScope.WINDOW).contents, expected);
|
||||
testObject.reprocess();
|
||||
assert.deepEqual(testObject.configurationModel.contents, { 'FolderSettingsModelParser': { 'resource': 'resource' } });
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('StandaloneConfigurationModelParser', () => {
|
||||
|
||||
test('parse tasks stand alone configuration model', () => {
|
||||
const testObject = new StandaloneConfigurationModelParser('tasks', 'tasks');
|
||||
|
||||
testObject.parse(JSON.stringify({ 'version': '1.1.1', 'tasks': [] }));
|
||||
|
||||
assert.deepEqual(testObject.configurationModel.contents, { 'tasks': { 'version': '1.1.1', 'tasks': [] } });
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('WorkspaceConfigurationChangeEvent', () => {
|
||||
@@ -194,4 +188,50 @@ suite('WorkspaceConfigurationChangeEvent', () => {
|
||||
assert.ok(!testObject.affectsConfiguration('files', URI.file(join('folder3', 'file3'))));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('AllKeysConfigurationChangeEvent', () => {
|
||||
|
||||
test('changeEvent affects keys for any resource', () => {
|
||||
const configuraiton = new Configuration(new ConfigurationModel({}, ['window.title', 'window.zoomLevel', 'window.restoreFullscreen', 'workbench.editor.enablePreview', 'window.restoreWindows']),
|
||||
new ConfigurationModel(), new ConfigurationModel(), new StrictResourceMap(), new ConfigurationModel(), new StrictResourceMap(), null);
|
||||
let testObject = new AllKeysConfigurationChangeEvent(configuraiton, ConfigurationTarget.USER, null);
|
||||
|
||||
assert.deepEqual(testObject.affectedKeys, ['window.title', 'window.zoomLevel', 'window.restoreFullscreen', 'workbench.editor.enablePreview', 'window.restoreWindows']);
|
||||
|
||||
assert.ok(testObject.affectsConfiguration('window.zoomLevel'));
|
||||
assert.ok(testObject.affectsConfiguration('window.zoomLevel', URI.file('file1')));
|
||||
assert.ok(testObject.affectsConfiguration('window.zoomLevel', URI.file('file2')));
|
||||
|
||||
assert.ok(testObject.affectsConfiguration('window.restoreFullscreen'));
|
||||
assert.ok(testObject.affectsConfiguration('window.restoreFullscreen', URI.file('file1')));
|
||||
assert.ok(testObject.affectsConfiguration('window.restoreFullscreen', URI.file('file2')));
|
||||
|
||||
assert.ok(testObject.affectsConfiguration('window.restoreWindows'));
|
||||
assert.ok(testObject.affectsConfiguration('window.restoreWindows', URI.file('file2')));
|
||||
assert.ok(testObject.affectsConfiguration('window.restoreWindows', URI.file('file1')));
|
||||
|
||||
assert.ok(testObject.affectsConfiguration('window.title'));
|
||||
assert.ok(testObject.affectsConfiguration('window.title', URI.file('file1')));
|
||||
assert.ok(testObject.affectsConfiguration('window.title', URI.file('file2')));
|
||||
|
||||
assert.ok(testObject.affectsConfiguration('window'));
|
||||
assert.ok(testObject.affectsConfiguration('window', URI.file('file1')));
|
||||
assert.ok(testObject.affectsConfiguration('window', URI.file('file2')));
|
||||
|
||||
assert.ok(testObject.affectsConfiguration('workbench.editor.enablePreview'));
|
||||
assert.ok(testObject.affectsConfiguration('workbench.editor.enablePreview', URI.file('file2')));
|
||||
assert.ok(testObject.affectsConfiguration('workbench.editor.enablePreview', URI.file('file1')));
|
||||
|
||||
assert.ok(testObject.affectsConfiguration('workbench.editor'));
|
||||
assert.ok(testObject.affectsConfiguration('workbench.editor', URI.file('file2')));
|
||||
assert.ok(testObject.affectsConfiguration('workbench.editor', URI.file('file1')));
|
||||
|
||||
assert.ok(testObject.affectsConfiguration('workbench'));
|
||||
assert.ok(testObject.affectsConfiguration('workbench', URI.file('file2')));
|
||||
assert.ok(testObject.affectsConfiguration('workbench', URI.file('file1')));
|
||||
|
||||
assert.ok(!testObject.affectsConfiguration('files'));
|
||||
assert.ok(!testObject.affectsConfiguration('files', URI.file('file1')));
|
||||
});
|
||||
});
|
||||
@@ -18,7 +18,7 @@ import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import extfs = require('vs/base/node/extfs');
|
||||
import { TestTextFileService, TestTextResourceConfigurationService, workbenchInstantiationService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import { TestTextFileService, TestTextResourceConfigurationService, workbenchInstantiationService, TestLifecycleService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import uuid = require('vs/base/common/uuid');
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService';
|
||||
@@ -33,12 +33,12 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
|
||||
import { IChoiceService } from 'vs/platform/message/common/message';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
|
||||
import { mkdirp } from 'vs/base/node/pfs';
|
||||
|
||||
class SettingsTestEnvironmentService extends EnvironmentService {
|
||||
|
||||
constructor(args: ParsedArgs, _execPath: string, private customAppSettingsHome) {
|
||||
constructor(args: ParsedArgs, _execPath: string, private customAppSettingsHome: string) {
|
||||
super(args, _execPath);
|
||||
}
|
||||
|
||||
@@ -49,9 +49,9 @@ suite('ConfigurationEditingService', () => {
|
||||
|
||||
let instantiationService: TestInstantiationService;
|
||||
let testObject: ConfigurationEditingService;
|
||||
let parentDir;
|
||||
let workspaceDir;
|
||||
let globalSettingsFile;
|
||||
let parentDir: string;
|
||||
let workspaceDir: string;
|
||||
let globalSettingsFile: string;
|
||||
let workspaceSettingsDir;
|
||||
|
||||
suiteSetup(() => {
|
||||
@@ -81,22 +81,15 @@ suite('ConfigurationEditingService', () => {
|
||||
.then(() => setUpServices());
|
||||
});
|
||||
|
||||
function setUpWorkspace(): TPromise<void> {
|
||||
return new TPromise<void>((c, e) => {
|
||||
const id = uuid.generateUuid();
|
||||
parentDir = path.join(os.tmpdir(), 'vsctests', id);
|
||||
workspaceDir = path.join(parentDir, 'workspaceconfig', id);
|
||||
globalSettingsFile = path.join(workspaceDir, 'config.json');
|
||||
// {{SQL CARBON EDIT}}
|
||||
workspaceSettingsDir = path.join(workspaceDir, '.sqlops');
|
||||
extfs.mkdirp(workspaceSettingsDir, 493, (error) => {
|
||||
if (error) {
|
||||
e(error);
|
||||
} else {
|
||||
c(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
function setUpWorkspace(): TPromise<boolean> {
|
||||
const id = uuid.generateUuid();
|
||||
parentDir = path.join(os.tmpdir(), 'vsctests', id);
|
||||
workspaceDir = path.join(parentDir, 'workspaceconfig', id);
|
||||
globalSettingsFile = path.join(workspaceDir, 'config.json');
|
||||
// {{SQL CARBON EDIT}}
|
||||
workspaceSettingsDir = path.join(workspaceDir, '.sqlops');
|
||||
|
||||
return mkdirp(workspaceSettingsDir, 493);
|
||||
}
|
||||
|
||||
function setUpServices(noWorkspace: boolean = false): TPromise<void> {
|
||||
@@ -106,12 +99,11 @@ suite('ConfigurationEditingService', () => {
|
||||
instantiationService = <TestInstantiationService>workbenchInstantiationService();
|
||||
const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile);
|
||||
instantiationService.stub(IEnvironmentService, environmentService);
|
||||
const workspacesService = instantiationService.stub(IWorkspacesService, {});
|
||||
const workspaceService = new WorkspaceService(environmentService, workspacesService);
|
||||
const workspaceService = new WorkspaceService(environmentService);
|
||||
instantiationService.stub(IWorkspaceContextService, workspaceService);
|
||||
return workspaceService.initialize(noWorkspace ? <IWindowConfiguration>{} : workspaceDir).then(() => {
|
||||
return workspaceService.initialize(noWorkspace ? {} as IWindowConfiguration : workspaceDir).then(() => {
|
||||
instantiationService.stub(IConfigurationService, workspaceService);
|
||||
instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), new TestConfigurationService(), { disableWatcher: true }));
|
||||
instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), new TestConfigurationService(), new TestLifecycleService(), { disableWatcher: true }));
|
||||
instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService));
|
||||
instantiationService.stub(ITextModelService, <ITextModelService>instantiationService.createInstance(TextModelResolverService));
|
||||
testObject = instantiationService.createInstance(ConfigurationEditingService);
|
||||
@@ -214,6 +206,28 @@ suite('ConfigurationEditingService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('remove an existing setting - existing file', () => {
|
||||
fs.writeFileSync(globalSettingsFile, '{ "my.super.setting": "my.super.value", "configurationEditing.service.testSetting": "value" }');
|
||||
return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: undefined })
|
||||
.then(() => {
|
||||
const contents = fs.readFileSync(globalSettingsFile).toString('utf8');
|
||||
const parsed = json.parse(contents);
|
||||
assert.deepEqual(Object.keys(parsed), ['my.super.setting']);
|
||||
assert.equal(parsed['my.super.setting'], 'my.super.value');
|
||||
});
|
||||
});
|
||||
|
||||
test('remove non existing setting - existing file', () => {
|
||||
fs.writeFileSync(globalSettingsFile, '{ "my.super.setting": "my.super.value" }');
|
||||
return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: undefined })
|
||||
.then(() => {
|
||||
const contents = fs.readFileSync(globalSettingsFile).toString('utf8');
|
||||
const parsed = json.parse(contents);
|
||||
assert.deepEqual(Object.keys(parsed), ['my.super.setting']);
|
||||
assert.equal(parsed['my.super.setting'], 'my.super.value');
|
||||
});
|
||||
});
|
||||
|
||||
test('write workspace standalone setting - empty file', () => {
|
||||
return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks.service.testSetting', value: 'value' })
|
||||
.then(() => {
|
||||
@@ -249,11 +263,10 @@ suite('ConfigurationEditingService', () => {
|
||||
});
|
||||
|
||||
test('write workspace standalone setting - existing file - full JSON', () => {
|
||||
const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['launch']);
|
||||
const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
|
||||
fs.writeFileSync(target, '{ "my.super.setting": "my.super.value" }');
|
||||
return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } })
|
||||
.then(() => {
|
||||
const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
|
||||
const contents = fs.readFileSync(target).toString('utf8');
|
||||
const parsed = json.parse(contents);
|
||||
|
||||
@@ -263,11 +276,10 @@ suite('ConfigurationEditingService', () => {
|
||||
});
|
||||
|
||||
test('write workspace standalone setting - existing file with JSON errors - full JSON', () => {
|
||||
const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['launch']);
|
||||
const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
|
||||
fs.writeFileSync(target, '{ "my.super.setting": '); // invalid JSON
|
||||
return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } })
|
||||
.then(() => {
|
||||
const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
|
||||
const contents = fs.readFileSync(target).toString('utf8');
|
||||
const parsed = json.parse(contents);
|
||||
|
||||
@@ -275,4 +287,25 @@ suite('ConfigurationEditingService', () => {
|
||||
assert.equal(parsed['tasks'][0]['taskName'], 'myTask');
|
||||
});
|
||||
});
|
||||
|
||||
test('write workspace standalone setting should replace complete file', () => {
|
||||
const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
|
||||
fs.writeFileSync(target, `{
|
||||
"version": "1.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"taskName": "myTask1"
|
||||
},
|
||||
{
|
||||
"taskName": "myTask2"
|
||||
}
|
||||
]
|
||||
}`);
|
||||
return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask1' }] } })
|
||||
.then(() => {
|
||||
const actual = fs.readFileSync(target).toString('utf8');
|
||||
const expected = JSON.stringify({ 'version': '1.0.0', tasks: [{ 'taskName': 'myTask1' }] }, null, '\t');
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -23,8 +23,8 @@ import { WorkspaceService } from 'vs/workbench/services/configuration/node/confi
|
||||
import { ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/node/configurationEditingService';
|
||||
import { FileChangeType, FileChangesEvent, IFileService } from 'vs/platform/files/common/files';
|
||||
import { IWorkspaceContextService, WorkbenchState, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace';
|
||||
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { workbenchInstantiationService, TestTextResourceConfigurationService, TestTextFileService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import { ConfigurationTarget, IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
|
||||
import { workbenchInstantiationService, TestTextResourceConfigurationService, TestTextFileService, TestLifecycleService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import { FileService } from 'vs/workbench/services/files/node/fileService';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
@@ -32,6 +32,9 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
|
||||
import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing';
|
||||
import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService';
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
|
||||
import { mkdirp } from 'vs/base/node/pfs';
|
||||
|
||||
class SettingsTestEnvironmentService extends EnvironmentService {
|
||||
|
||||
@@ -53,13 +56,7 @@ function setUpFolder(folderName: string, parentDir: string): TPromise<string> {
|
||||
// {{SQL CARBON EDIT}}
|
||||
const workspaceSettingsDir = path.join(folderDir, '.sqlops');
|
||||
return new TPromise((c, e) => {
|
||||
extfs.mkdirp(workspaceSettingsDir, 493, (error) => {
|
||||
if (error) {
|
||||
e(error);
|
||||
return null;
|
||||
}
|
||||
c(folderDir);
|
||||
});
|
||||
extfs.mkdirp(workspaceSettingsDir, 493);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -68,7 +65,7 @@ function setUpWorkspace(folders: string[]): TPromise<{ parentDir: string, config
|
||||
const id = uuid.generateUuid();
|
||||
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
|
||||
|
||||
return createDir(parentDir)
|
||||
return mkdirp(parentDir, 493)
|
||||
.then(() => {
|
||||
const configPath = path.join(parentDir, 'vsctests.code-workspace');
|
||||
const workspace = { folders: folders.map(path => ({ path })) };
|
||||
@@ -80,617 +77,10 @@ function setUpWorkspace(folders: string[]): TPromise<{ parentDir: string, config
|
||||
|
||||
}
|
||||
|
||||
function createDir(dir: string): TPromise<void> {
|
||||
return new TPromise((c, e) => {
|
||||
extfs.mkdirp(dir, 493, (error) => {
|
||||
if (error) {
|
||||
e(error);
|
||||
return null;
|
||||
}
|
||||
c(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
suite('WorkspaceContextService - Folder', () => {
|
||||
|
||||
let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceResource: string, workspaceContextService: IWorkspaceContextService;
|
||||
|
||||
setup(() => {
|
||||
return setUpFolderWorkspace(workspaceName)
|
||||
.then(({ parentDir, folderDir }) => {
|
||||
parentResource = parentDir;
|
||||
workspaceResource = folderDir;
|
||||
const globalSettingsFile = path.join(parentDir, 'settings.json');
|
||||
const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile);
|
||||
workspaceContextService = new WorkspaceService(environmentService, null);
|
||||
return (<WorkspaceService>workspaceContextService).initialize(folderDir);
|
||||
});
|
||||
});
|
||||
|
||||
teardown(done => {
|
||||
if (workspaceContextService) {
|
||||
(<WorkspaceService>workspaceContextService).dispose();
|
||||
}
|
||||
if (parentResource) {
|
||||
extfs.del(parentResource, os.tmpdir(), () => { }, done);
|
||||
}
|
||||
});
|
||||
|
||||
test('getWorkspace()', () => {
|
||||
const actual = workspaceContextService.getWorkspace();
|
||||
|
||||
assert.equal(actual.folders.length, 1);
|
||||
assert.equal(actual.folders[0].uri.fsPath, URI.file(workspaceResource).fsPath);
|
||||
assert.equal(actual.folders[0].name, workspaceName);
|
||||
assert.equal(actual.folders[0].index, 0);
|
||||
assert.ok(!actual.configuration);
|
||||
});
|
||||
|
||||
test('getWorkbenchState()', () => {
|
||||
const actual = workspaceContextService.getWorkbenchState();
|
||||
|
||||
assert.equal(actual, WorkbenchState.FOLDER);
|
||||
});
|
||||
|
||||
test('getWorkspaceFolder()', () => {
|
||||
const actual = workspaceContextService.getWorkspaceFolder(URI.file(path.join(workspaceResource, 'a')));
|
||||
|
||||
assert.equal(actual, workspaceContextService.getWorkspace().folders[0]);
|
||||
});
|
||||
|
||||
test('isCurrentWorkspace() => true', () => {
|
||||
assert.ok(workspaceContextService.isCurrentWorkspace(workspaceResource));
|
||||
});
|
||||
|
||||
test('isCurrentWorkspace() => false', () => {
|
||||
assert.ok(!workspaceContextService.isCurrentWorkspace(workspaceResource + 'abc'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('WorkspaceContextService - Workspace', () => {
|
||||
|
||||
let parentResource: string, testObject: WorkspaceService;
|
||||
|
||||
setup(() => {
|
||||
return setUpWorkspace(['a', 'b'])
|
||||
.then(({ parentDir, configPath }) => {
|
||||
|
||||
parentResource = parentDir;
|
||||
|
||||
const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, path.join(parentDir, 'settings.json'));
|
||||
const workspaceService = new WorkspaceService(environmentService, null);
|
||||
|
||||
const instantiationService = <TestInstantiationService>workbenchInstantiationService();
|
||||
instantiationService.stub(IWorkspaceContextService, workspaceService);
|
||||
instantiationService.stub(IConfigurationService, workspaceService);
|
||||
instantiationService.stub(IEnvironmentService, environmentService);
|
||||
|
||||
return workspaceService.initialize({ id: configPath, configPath }).then(() => {
|
||||
|
||||
instantiationService.stub(IFileService, new FileService(<IWorkspaceContextService>workspaceService, new TestTextResourceConfigurationService(), workspaceService, { disableWatcher: true }));
|
||||
instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService));
|
||||
instantiationService.stub(ITextModelService, <ITextModelService>instantiationService.createInstance(TextModelResolverService));
|
||||
workspaceService.setInstantiationService(instantiationService);
|
||||
|
||||
testObject = workspaceService;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
teardown(done => {
|
||||
if (testObject) {
|
||||
(<WorkspaceService>testObject).dispose();
|
||||
}
|
||||
if (parentResource) {
|
||||
extfs.del(parentResource, os.tmpdir(), () => { }, done);
|
||||
}
|
||||
});
|
||||
|
||||
test('workspace folders', () => {
|
||||
const actual = testObject.getWorkspace().folders;
|
||||
|
||||
assert.equal(actual.length, 2);
|
||||
assert.equal(path.basename(actual[0].uri.fsPath), 'a');
|
||||
assert.equal(path.basename(actual[1].uri.fsPath), 'b');
|
||||
});
|
||||
|
||||
test('add folders', () => {
|
||||
const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath);
|
||||
return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }])
|
||||
.then(() => {
|
||||
const actual = testObject.getWorkspace().folders;
|
||||
|
||||
assert.equal(actual.length, 4);
|
||||
assert.equal(path.basename(actual[0].uri.fsPath), 'a');
|
||||
assert.equal(path.basename(actual[1].uri.fsPath), 'b');
|
||||
assert.equal(path.basename(actual[2].uri.fsPath), 'd');
|
||||
assert.equal(path.basename(actual[3].uri.fsPath), 'c');
|
||||
});
|
||||
});
|
||||
|
||||
test('add folders (with name)', () => {
|
||||
const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath);
|
||||
return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')), name: 'DDD' }, { uri: URI.file(path.join(workspaceDir, 'c')), name: 'CCC' }])
|
||||
.then(() => {
|
||||
const actual = testObject.getWorkspace().folders;
|
||||
|
||||
assert.equal(actual.length, 4);
|
||||
assert.equal(path.basename(actual[0].uri.fsPath), 'a');
|
||||
assert.equal(path.basename(actual[1].uri.fsPath), 'b');
|
||||
assert.equal(path.basename(actual[2].uri.fsPath), 'd');
|
||||
assert.equal(path.basename(actual[3].uri.fsPath), 'c');
|
||||
assert.equal(actual[2].name, 'DDD');
|
||||
assert.equal(actual[3].name, 'CCC');
|
||||
});
|
||||
});
|
||||
|
||||
test('add folders triggers change event', () => {
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeWorkspaceFolders(target);
|
||||
const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath);
|
||||
const addedFolders = [{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }];
|
||||
return testObject.addFolders(addedFolders)
|
||||
.then(() => {
|
||||
assert.ok(target.calledOnce);
|
||||
const actual = <IWorkspaceFoldersChangeEvent>target.args[0][0];
|
||||
assert.deepEqual(actual.added.map(r => r.uri.toString()), addedFolders.map(a => a.uri.toString()));
|
||||
assert.deepEqual(actual.removed, []);
|
||||
assert.deepEqual(actual.changed, []);
|
||||
});
|
||||
});
|
||||
|
||||
test('remove folders', () => {
|
||||
return testObject.removeFolders([testObject.getWorkspace().folders[0].uri])
|
||||
.then(() => {
|
||||
const actual = testObject.getWorkspace().folders;
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(path.basename(actual[0].uri.fsPath), 'b');
|
||||
});
|
||||
});
|
||||
|
||||
test('remove folders triggers change event', () => {
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeWorkspaceFolders(target);
|
||||
const removedFolder = testObject.getWorkspace().folders[0];
|
||||
return testObject.removeFolders([removedFolder.uri])
|
||||
.then(() => {
|
||||
assert.ok(target.calledOnce);
|
||||
const actual = <IWorkspaceFoldersChangeEvent>target.args[0][0];
|
||||
assert.deepEqual(actual.added, []);
|
||||
assert.deepEqual(actual.removed.map(r => r.uri.toString()), [removedFolder.uri.toString()]);
|
||||
assert.deepEqual(actual.changed.map(c => c.uri.toString()), [testObject.getWorkspace().folders[0].uri.toString()]);
|
||||
});
|
||||
});
|
||||
|
||||
test('reorder folders trigger change event', () => {
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeWorkspaceFolders(target);
|
||||
const workspace = { folders: [{ path: testObject.getWorkspace().folders[1].uri.fsPath }, { path: testObject.getWorkspace().folders[0].uri.fsPath }] };
|
||||
fs.writeFileSync(testObject.getWorkspace().configuration.fsPath, JSON.stringify(workspace, null, '\t'));
|
||||
return testObject.reloadConfiguration()
|
||||
.then(() => {
|
||||
assert.ok(target.calledOnce);
|
||||
const actual = <IWorkspaceFoldersChangeEvent>target.args[0][0];
|
||||
assert.deepEqual(actual.added, []);
|
||||
assert.deepEqual(actual.removed, []);
|
||||
assert.deepEqual(actual.changed.map(c => c.uri.toString()), testObject.getWorkspace().folders.map(f => f.uri.toString()).reverse());
|
||||
});
|
||||
});
|
||||
|
||||
test('rename folders trigger change event', () => {
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeWorkspaceFolders(target);
|
||||
const workspace = { folders: [{ path: testObject.getWorkspace().folders[0].uri.fsPath, name: '1' }, { path: testObject.getWorkspace().folders[1].uri.fsPath }] };
|
||||
fs.writeFileSync(testObject.getWorkspace().configuration.fsPath, JSON.stringify(workspace, null, '\t'));
|
||||
return testObject.reloadConfiguration()
|
||||
.then(() => {
|
||||
assert.ok(target.calledOnce);
|
||||
const actual = <IWorkspaceFoldersChangeEvent>target.args[0][0];
|
||||
assert.deepEqual(actual.added, []);
|
||||
assert.deepEqual(actual.removed, []);
|
||||
assert.deepEqual(actual.changed.map(c => c.uri.toString()), [testObject.getWorkspace().folders[0].uri.toString()]);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('WorkspaceConfigurationService - Folder', () => {
|
||||
|
||||
let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceDir: string, testObject: IConfigurationService, globalSettingsFile: string;
|
||||
|
||||
suiteSetup(() => {
|
||||
const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': '_test',
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'configurationService.folder.testSetting': {
|
||||
'type': 'string',
|
||||
'default': 'isSet'
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
return setUpFolderWorkspace(workspaceName)
|
||||
.then(({ parentDir, folderDir }) => {
|
||||
|
||||
parentResource = parentDir;
|
||||
workspaceDir = folderDir;
|
||||
globalSettingsFile = path.join(parentDir, 'settings.json');
|
||||
|
||||
const instantiationService = <TestInstantiationService>workbenchInstantiationService();
|
||||
const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile);
|
||||
const workspaceService = new WorkspaceService(environmentService, null);
|
||||
instantiationService.stub(IWorkspaceContextService, workspaceService);
|
||||
instantiationService.stub(IConfigurationService, workspaceService);
|
||||
instantiationService.stub(IEnvironmentService, environmentService);
|
||||
|
||||
return workspaceService.initialize(folderDir).then(() => {
|
||||
instantiationService.stub(IFileService, new FileService(<IWorkspaceContextService>workspaceService, new TestTextResourceConfigurationService(), workspaceService, { disableWatcher: true }));
|
||||
instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService));
|
||||
instantiationService.stub(ITextModelService, <ITextModelService>instantiationService.createInstance(TextModelResolverService));
|
||||
workspaceService.setInstantiationService(instantiationService);
|
||||
testObject = workspaceService;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
teardown(done => {
|
||||
if (testObject) {
|
||||
(<WorkspaceService>testObject).dispose();
|
||||
}
|
||||
if (parentResource) {
|
||||
extfs.del(parentResource, os.tmpdir(), () => { }, done);
|
||||
}
|
||||
});
|
||||
|
||||
test('defaults', () => {
|
||||
assert.deepEqual(testObject.getValue('configurationService'), { 'folder': { 'testSetting': 'isSet' } });
|
||||
});
|
||||
|
||||
test('globals override defaults', () => {
|
||||
fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }');
|
||||
return testObject.reloadConfiguration()
|
||||
.then(() => assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'userValue'));
|
||||
});
|
||||
|
||||
test('globals', () => {
|
||||
fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }');
|
||||
return testObject.reloadConfiguration()
|
||||
.then(() => assert.equal(testObject.getValue('testworkbench.editor.tabs'), true));
|
||||
});
|
||||
|
||||
test('workspace settings', () => {
|
||||
// {{SQL CARBON EDIT}}
|
||||
fs.writeFileSync(path.join(workspaceDir, '.sqlops', 'settings.json'), '{ "testworkbench.editor.icons": true }');
|
||||
return testObject.reloadConfiguration()
|
||||
.then(() => assert.equal(testObject.getValue('testworkbench.editor.icons'), true));
|
||||
});
|
||||
|
||||
test('workspace settings override user settings', () => {
|
||||
fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }');
|
||||
// {{SQL CARBON EDIT}}
|
||||
fs.writeFileSync(path.join(workspaceDir, '.sqlops', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }');
|
||||
return testObject.reloadConfiguration()
|
||||
.then(() => assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue'));
|
||||
});
|
||||
|
||||
test('workspace change triggers event', () => {
|
||||
// {{SQL CARBON EDIT}}
|
||||
const settingsFile = path.join(workspaceDir, '.sqlops', 'settings.json');
|
||||
fs.writeFileSync(settingsFile, '{ "configurationService.folder.testSetting": "workspaceValue" }');
|
||||
const event = new FileChangesEvent([{ resource: URI.file(settingsFile), type: FileChangeType.ADDED }]);
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeConfiguration(target);
|
||||
return (<WorkspaceService>testObject).handleWorkspaceFileEvents(event)
|
||||
.then(() => {
|
||||
assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue');
|
||||
assert.ok(target.called);
|
||||
});
|
||||
});
|
||||
|
||||
test('reload configuration emits events after global configuraiton changes', () => {
|
||||
fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }');
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeConfiguration(target);
|
||||
return testObject.reloadConfiguration().then(() => assert.ok(target.called));
|
||||
});
|
||||
|
||||
test('reload configuration emits events after workspace configuraiton changes', () => {
|
||||
// {{SQL CARBON EDIT}}
|
||||
fs.writeFileSync(path.join(workspaceDir, '.sqlops', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }');
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeConfiguration(target);
|
||||
return testObject.reloadConfiguration().then(() => assert.ok(target.called));
|
||||
});
|
||||
|
||||
test('reload configuration should not emit event if no changes', () => {
|
||||
fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }');
|
||||
// {{SQL CARBON EDIT}}
|
||||
fs.writeFileSync(path.join(workspaceDir, '.sqlops', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }');
|
||||
return testObject.reloadConfiguration()
|
||||
.then(() => {
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeConfiguration(() => { target(); });
|
||||
return testObject.reloadConfiguration()
|
||||
.then(() => assert.ok(!target.called));
|
||||
});
|
||||
});
|
||||
|
||||
test('inspect', () => {
|
||||
let actual = testObject.inspect('something.missing');
|
||||
assert.equal(actual.default, void 0);
|
||||
assert.equal(actual.user, void 0);
|
||||
assert.equal(actual.workspace, void 0);
|
||||
assert.equal(actual.workspaceFolder, void 0);
|
||||
assert.equal(actual.value, void 0);
|
||||
|
||||
actual = testObject.inspect('configurationService.folder.testSetting');
|
||||
assert.equal(actual.default, 'isSet');
|
||||
assert.equal(actual.user, void 0);
|
||||
assert.equal(actual.workspace, void 0);
|
||||
assert.equal(actual.workspaceFolder, void 0);
|
||||
assert.equal(actual.value, 'isSet');
|
||||
|
||||
fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }');
|
||||
return testObject.reloadConfiguration()
|
||||
.then(() => {
|
||||
actual = testObject.inspect('configurationService.folder.testSetting');
|
||||
assert.equal(actual.default, 'isSet');
|
||||
assert.equal(actual.user, 'userValue');
|
||||
assert.equal(actual.workspace, void 0);
|
||||
assert.equal(actual.workspaceFolder, void 0);
|
||||
assert.equal(actual.value, 'userValue');
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
fs.writeFileSync(path.join(workspaceDir, '.sqlops', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }');
|
||||
|
||||
return testObject.reloadConfiguration()
|
||||
.then(() => {
|
||||
actual = testObject.inspect('configurationService.folder.testSetting');
|
||||
assert.equal(actual.default, 'isSet');
|
||||
assert.equal(actual.user, 'userValue');
|
||||
assert.equal(actual.workspace, 'workspaceValue');
|
||||
assert.equal(actual.workspaceFolder, void 0);
|
||||
assert.equal(actual.value, 'workspaceValue');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('keys', () => {
|
||||
let actual = testObject.keys();
|
||||
assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1);
|
||||
assert.deepEqual(actual.user, []);
|
||||
assert.deepEqual(actual.workspace, []);
|
||||
assert.deepEqual(actual.workspaceFolder, []);
|
||||
|
||||
fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }');
|
||||
return testObject.reloadConfiguration()
|
||||
.then(() => {
|
||||
actual = testObject.keys();
|
||||
assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1);
|
||||
assert.deepEqual(actual.user, ['configurationService.folder.testSetting']);
|
||||
assert.deepEqual(actual.workspace, []);
|
||||
assert.deepEqual(actual.workspaceFolder, []);
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
fs.writeFileSync(path.join(workspaceDir, '.sqlops', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }');
|
||||
|
||||
return testObject.reloadConfiguration()
|
||||
.then(() => {
|
||||
actual = testObject.keys();
|
||||
assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1);
|
||||
assert.deepEqual(actual.user, ['configurationService.folder.testSetting']);
|
||||
assert.deepEqual(actual.workspace, ['configurationService.folder.testSetting']);
|
||||
assert.deepEqual(actual.workspaceFolder, []);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('update user configuration', () => {
|
||||
return testObject.updateValue('configurationService.folder.testSetting', 'value', ConfigurationTarget.USER)
|
||||
.then(() => assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'value'));
|
||||
});
|
||||
|
||||
test('update workspace configuration', () => {
|
||||
return testObject.updateValue('tasks.service.testSetting', 'value', ConfigurationTarget.WORKSPACE)
|
||||
.then(() => assert.equal(testObject.getValue('tasks.service.testSetting'), 'value'));
|
||||
});
|
||||
|
||||
test('update tasks configuration', () => {
|
||||
return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, ConfigurationTarget.WORKSPACE)
|
||||
.then(() => assert.deepEqual(testObject.getValue('tasks'), { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }));
|
||||
});
|
||||
|
||||
test('update user configuration should trigger change event before promise is resolve', () => {
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeConfiguration(target);
|
||||
return testObject.updateValue('configurationService.folder.testSetting', 'value', ConfigurationTarget.USER)
|
||||
.then(() => assert.ok(target.called));
|
||||
});
|
||||
|
||||
test('update workspace configuration should trigger change event before promise is resolve', () => {
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeConfiguration(target);
|
||||
return testObject.updateValue('configurationService.folder.testSetting', 'value', ConfigurationTarget.WORKSPACE)
|
||||
.then(() => assert.ok(target.called));
|
||||
});
|
||||
|
||||
test('update task configuration should trigger change event before promise is resolve', () => {
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeConfiguration(target);
|
||||
return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, ConfigurationTarget.WORKSPACE)
|
||||
.then(() => assert.ok(target.called));
|
||||
});
|
||||
|
||||
test('initialize with different folder triggers configuration event if there are changes', () => {
|
||||
return setUpFolderWorkspace(`testWorkspace${uuid.generateUuid()}`)
|
||||
.then(({ folderDir }) => {
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeConfiguration(target);
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
fs.writeFileSync(path.join(folderDir, '.sqlops', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue2" }');
|
||||
return (<WorkspaceService>testObject).initialize(folderDir)
|
||||
.then(() => {
|
||||
assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue2');
|
||||
assert.ok(target.called);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('initialize with different folder triggers configuration event if there are no changes', () => {
|
||||
fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "workspaceValue2" }');
|
||||
return testObject.reloadConfiguration()
|
||||
.then(() => setUpFolderWorkspace(`testWorkspace${uuid.generateUuid()}`))
|
||||
.then(({ folderDir }) => {
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeConfiguration(() => target());
|
||||
// {{SQL CARBON EDIT}}
|
||||
fs.writeFileSync(path.join(folderDir, '.sqlops', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue2" }');
|
||||
return (<WorkspaceService>testObject).initialize(folderDir)
|
||||
.then(() => {
|
||||
assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue2');
|
||||
assert.ok(!target.called);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('WorkspaceConfigurationService - Update (Multiroot)', () => {
|
||||
|
||||
let parentResource: string, workspaceContextService: IWorkspaceContextService, jsonEditingServce: IJSONEditingService, testObject: IConfigurationService;
|
||||
|
||||
suiteSetup(() => {
|
||||
const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': '_test',
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'configurationService.workspace.testSetting': {
|
||||
'type': 'string',
|
||||
'default': 'isSet'
|
||||
},
|
||||
'configurationService.workspace.testResourceSetting': {
|
||||
'type': 'string',
|
||||
'default': 'isSet',
|
||||
scope: ConfigurationScope.RESOURCE
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
return setUpWorkspace(['1', '2'])
|
||||
.then(({ parentDir, configPath }) => {
|
||||
|
||||
parentResource = parentDir;
|
||||
|
||||
const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, path.join(parentDir, 'settings.json'));
|
||||
const workspaceService = new WorkspaceService(environmentService, null);
|
||||
|
||||
const instantiationService = <TestInstantiationService>workbenchInstantiationService();
|
||||
instantiationService.stub(IWorkspaceContextService, workspaceService);
|
||||
instantiationService.stub(IConfigurationService, workspaceService);
|
||||
instantiationService.stub(IEnvironmentService, environmentService);
|
||||
|
||||
return workspaceService.initialize({ id: configPath, configPath }).then(() => {
|
||||
|
||||
instantiationService.stub(IFileService, new FileService(<IWorkspaceContextService>workspaceService, new TestTextResourceConfigurationService(), workspaceService, { disableWatcher: true }));
|
||||
instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService));
|
||||
instantiationService.stub(ITextModelService, <ITextModelService>instantiationService.createInstance(TextModelResolverService));
|
||||
workspaceService.setInstantiationService(instantiationService);
|
||||
|
||||
workspaceContextService = workspaceService;
|
||||
jsonEditingServce = instantiationService.createInstance(JSONEditingService);
|
||||
testObject = workspaceService;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
teardown(done => {
|
||||
if (testObject) {
|
||||
(<WorkspaceService>testObject).dispose();
|
||||
}
|
||||
if (parentResource) {
|
||||
extfs.del(parentResource, os.tmpdir(), () => { }, done);
|
||||
}
|
||||
});
|
||||
|
||||
test('update user configuration', () => {
|
||||
return testObject.updateValue('configurationService.workspace.testSetting', 'userValue', ConfigurationTarget.USER)
|
||||
.then(() => assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'userValue'));
|
||||
});
|
||||
|
||||
test('update user configuration should trigger change event before promise is resolve', () => {
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeConfiguration(target);
|
||||
return testObject.updateValue('configurationService.workspace.testSetting', 'userValue', ConfigurationTarget.USER)
|
||||
.then(() => assert.ok(target.called));
|
||||
});
|
||||
|
||||
test('update workspace configuration', () => {
|
||||
return testObject.updateValue('configurationService.workspace.testSetting', 'workspaceValue', ConfigurationTarget.WORKSPACE)
|
||||
.then(() => assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'workspaceValue'));
|
||||
});
|
||||
|
||||
test('update workspace configuration should trigger change event before promise is resolve', () => {
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeConfiguration(target);
|
||||
return testObject.updateValue('configurationService.workspace.testSetting', 'workspaceValue', ConfigurationTarget.WORKSPACE)
|
||||
.then(() => assert.ok(target.called));
|
||||
});
|
||||
|
||||
test('update workspace folder configuration', () => {
|
||||
const workspace = workspaceContextService.getWorkspace();
|
||||
return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER)
|
||||
.then(() => assert.equal(testObject.getValue('configurationService.workspace.testResourceSetting', { resource: workspace.folders[0].uri }), 'workspaceFolderValue'));
|
||||
});
|
||||
|
||||
test('update workspace folder configuration should trigger change event before promise is resolve', () => {
|
||||
const workspace = workspaceContextService.getWorkspace();
|
||||
const target = sinon.spy();
|
||||
testObject.onDidChangeConfiguration(target);
|
||||
return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER)
|
||||
.then(() => assert.ok(target.called));
|
||||
});
|
||||
|
||||
test('update tasks configuration in a folder', () => {
|
||||
const workspace = workspaceContextService.getWorkspace();
|
||||
return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER)
|
||||
.then(() => assert.deepEqual(testObject.getValue('tasks', { resource: workspace.folders[0].uri }), { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }));
|
||||
});
|
||||
|
||||
test('update tasks configuration in a workspace is not supported', () => {
|
||||
const workspace = workspaceContextService.getWorkspace();
|
||||
return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE, true)
|
||||
.then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_TARGET));
|
||||
});
|
||||
|
||||
test('update launch configuration in a workspace is not supported', () => {
|
||||
const workspace = workspaceContextService.getWorkspace();
|
||||
return testObject.updateValue('launch', { 'version': '1.0.0', configurations: [{ 'name': 'myLaunch' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE, true)
|
||||
.then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_TARGET));
|
||||
});
|
||||
|
||||
test('task configurations are not read from workspace', () => {
|
||||
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'tasks', value: { 'version': '1.0' } }, true)
|
||||
.then(() => testObject.reloadConfiguration())
|
||||
.then(() => {
|
||||
const actual = testObject.inspect('tasks.version');
|
||||
assert.equal(actual.workspace, void 0);
|
||||
});
|
||||
});
|
||||
|
||||
test('launch configurations are not read from workspace', () => {
|
||||
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'launch', value: { 'version': '1.0' } }, true)
|
||||
.then(() => testObject.reloadConfiguration())
|
||||
.then(() => {
|
||||
const actual = testObject.inspect('launch.version');
|
||||
assert.equal(actual.workspace, void 0);
|
||||
});
|
||||
assert.equal(0, 0);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user