Vscode merge (#4582)

* Merge from vscode 37cb23d3dd4f9433d56d4ba5ea3203580719a0bd

* fix issues with merges

* bump node version in azpipe

* replace license headers

* remove duplicate launch task

* fix build errors

* fix build errors

* fix tslint issues

* working through package and linux build issues

* more work

* wip

* fix packaged builds

* working through linux build errors

* wip

* wip

* wip

* fix mac and linux file limits

* iterate linux pipeline

* disable editor typing

* revert series to parallel

* remove optimize vscode from linux

* fix linting issues

* revert testing change

* add work round for new node

* readd packaging for extensions

* fix issue with angular not resolving decorator dependencies
This commit is contained in:
Anthony Dresser
2019-03-19 17:44:35 -07:00
committed by GitHub
parent 833d197412
commit 87765e8673
1879 changed files with 54505 additions and 38058 deletions

View File

@@ -3,19 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
// {{SQL CARBON EDIT}}
export const FOLDER_CONFIG_FOLDER_NAME = '.azuredatastudio';
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');
export interface IWorkspaceConfigurationService extends IConfigurationService {
}
export const defaultSettingsSchemaId = 'vscode://schemas/settings/default';
export const userSettingsSchemaId = 'vscode://schemas/settings/user';
export const workspaceSettingsSchemaId = 'vscode://schemas/settings/workspace';

View File

@@ -6,7 +6,6 @@
import * as nls from 'vs/nls';
import { URI } from 'vs/base/common/uri';
import * as json from 'vs/base/common/json';
import * as encoding from 'vs/base/node/encoding';
import * as strings from 'vs/base/common/strings';
import { setProperty } from 'vs/base/common/jsonEdit';
import { Queue } from 'vs/base/common/async';
@@ -22,7 +21,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile
import { IConfigurationService, IConfigurationOverrides, keyFromOverrideIdentifier, ConfigurationTarget } from 'vs/platform/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 { ITextModelService, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
import { OVERRIDE_PROPERTY_PATTERN, IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ITextModel } from 'vs/editor/common/model';
@@ -106,7 +105,7 @@ export interface IConfigurationEditingOptions {
interface IConfigurationEditOperation extends IConfigurationValue {
target: ConfigurationTarget;
jsonPath: json.JSONPath;
resource: URI;
resource?: URI;
workspaceStandAloneConfigurationKey?: string;
}
@@ -158,7 +157,7 @@ export class ConfigurationEditingService {
private async writeToBuffer(model: ITextModel, operation: IConfigurationEditOperation, save: boolean): Promise<any> {
const edit = this.getEdits(model, operation)[0];
if (edit && this.applyEditsToBuffer(edit, model) && save) {
return this.textFileService.save(operation.resource, { skipSaveParticipants: true /* programmatic change */ });
return this.textFileService.save(operation.resource!, { skipSaveParticipants: true /* programmatic change */ });
}
}
@@ -175,7 +174,7 @@ export class ConfigurationEditingService {
return false;
}
private onError(error: ConfigurationEditingError, operation: IConfigurationEditOperation, scopes: IConfigurationOverrides): void {
private onError(error: ConfigurationEditingError, operation: IConfigurationEditOperation, scopes: IConfigurationOverrides | undefined): void {
switch (error.code) {
case ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION:
this.onInvalidConfigurationError(error, operation);
@@ -196,7 +195,7 @@ export class ConfigurationEditingService {
this.notificationService.prompt(Severity.Error, error.message,
[{
label: openStandAloneConfigurationActionLabel,
run: () => this.openFile(operation.resource)
run: () => this.openFile(operation.resource!)
}]
);
} else {
@@ -209,7 +208,7 @@ export class ConfigurationEditingService {
}
}
private onConfigurationFileDirtyError(error: ConfigurationEditingError, operation: IConfigurationEditOperation, scopes: IConfigurationOverrides): void {
private onConfigurationFileDirtyError(error: ConfigurationEditingError, operation: IConfigurationEditOperation, scopes: IConfigurationOverrides | undefined): void {
const openStandAloneConfigurationActionLabel = operation.workspaceStandAloneConfigurationKey === TASKS_CONFIGURATION_KEY ? nls.localize('openTasksConfiguration', "Open Tasks Configuration")
: operation.workspaceStandAloneConfigurationKey === LAUNCH_CONFIGURATION_KEY ? nls.localize('openLaunchConfiguration', "Open Launch Configuration")
: null;
@@ -218,13 +217,13 @@ export class ConfigurationEditingService {
[{
label: nls.localize('saveAndRetry', "Save and Retry"),
run: () => {
const key = operation.key ? `${operation.workspaceStandAloneConfigurationKey}.${operation.key}` : operation.workspaceStandAloneConfigurationKey;
const key = operation.key ? `${operation.workspaceStandAloneConfigurationKey}.${operation.key}` : operation.workspaceStandAloneConfigurationKey!;
this.writeConfiguration(operation.target, { key, value: operation.value }, <ConfigurationEditingOptions>{ force: true, scopes });
}
},
{
label: openStandAloneConfigurationActionLabel,
run: () => this.openFile(operation.resource)
run: () => this.openFile(operation.resource!)
}]
);
} else {
@@ -296,7 +295,13 @@ export class ConfigurationEditingService {
case ConfigurationTarget.WORKSPACE:
return nls.localize('errorInvalidConfigurationWorkspace', "Unable to write into workspace settings. Please open the workspace settings to correct errors/warnings in the file and try again.");
case ConfigurationTarget.WORKSPACE_FOLDER:
const workspaceFolderName = this.contextService.getWorkspaceFolder(operation.resource).name;
let workspaceFolderName: string = '<<unknown>>';
if (operation.resource) {
const folder = this.contextService.getWorkspaceFolder(operation.resource);
if (folder) {
workspaceFolderName = folder.name;
}
}
return nls.localize('errorInvalidConfigurationFolder', "Unable to write into folder settings. Please open the '{0}' folder settings to correct errors/warnings in it and try again.", workspaceFolderName);
}
return '';
@@ -314,7 +319,13 @@ export class ConfigurationEditingService {
case ConfigurationTarget.WORKSPACE:
return nls.localize('errorConfigurationFileDirtyWorkspace', "Unable to write into workspace settings because the file is dirty. Please save the workspace settings file first and then try again.");
case ConfigurationTarget.WORKSPACE_FOLDER:
const workspaceFolderName = this.contextService.getWorkspaceFolder(operation.resource).name;
let workspaceFolderName: string = '<<unknown>>';
if (operation.resource) {
const folder = this.contextService.getWorkspaceFolder(operation.resource);
if (folder) {
workspaceFolderName = folder.name;
}
}
return nls.localize('errorConfigurationFileDirtyFolder', "Unable to write into folder settings because the file is dirty. Please save the '{0}' folder settings file first and then try again.", workspaceFolderName);
}
return '';
@@ -352,10 +363,10 @@ export class ConfigurationEditingService {
return setProperty(model.getValue(), jsonPath, value, { tabSize, insertSpaces, eol });
}
private async resolveModelReference(resource: URI): Promise<IReference<ITextEditorModel>> {
private async resolveModelReference(resource: URI): Promise<IReference<IResolvedTextEditorModel>> {
const exists = await this.fileService.existsFile(resource);
if (!exists) {
await this.fileService.updateContent(resource, '{}', { encoding: encoding.UTF8 });
await this.fileService.updateContent(resource, '{}', { encoding: 'utf8' });
}
return this.textModelResolverService.createModelReference(resource);
}
@@ -371,7 +382,7 @@ export class ConfigurationEditingService {
return parseErrors.length > 0;
}
private resolveAndValidate(target: ConfigurationTarget, operation: IConfigurationEditOperation, checkDirty: boolean, overrides: IConfigurationOverrides): Promise<IReference<ITextEditorModel>> {
private resolveAndValidate(target: ConfigurationTarget, operation: IConfigurationEditOperation, checkDirty: boolean, overrides: IConfigurationOverrides): Promise<IReference<IResolvedTextEditorModel>> {
// Any key must be a known setting from the registry (unless this is a standalone config)
if (!operation.workspaceStandAloneConfigurationKey) {
@@ -420,6 +431,10 @@ export class ConfigurationEditingService {
}
}
if (!operation.resource) {
return this.reject(ConfigurationEditingErrorCode.ERROR_INVALID_FOLDER_TARGET, target, operation);
}
return this.resolveModelReference(operation.resource)
.then(reference => {
const model = reference.object.textEditorModel;
@@ -447,14 +462,14 @@ export class ConfigurationEditingService {
// Check for prefix
if (config.key === key) {
const jsonPath = this.isWorkspaceConfigurationResource(resource) ? [key] : [];
return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource, workspaceStandAloneConfigurationKey: key, target };
return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource: resource || undefined, workspaceStandAloneConfigurationKey: key, target };
}
// Check for prefix.<setting>
const keyPrefix = `${key}.`;
if (config.key.indexOf(keyPrefix) === 0) {
const jsonPath = this.isWorkspaceConfigurationResource(resource) ? [key, config.key.substr(keyPrefix.length)] : [config.key.substr(keyPrefix.length)];
return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource, workspaceStandAloneConfigurationKey: key, target };
return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource: resource || undefined, workspaceStandAloneConfigurationKey: key, target };
}
}
}
@@ -469,15 +484,15 @@ export class ConfigurationEditingService {
if (this.isWorkspaceConfigurationResource(resource)) {
jsonPath = ['settings', ...jsonPath];
}
return { key, jsonPath, value: config.value, resource, target };
return { key, jsonPath, value: config.value, resource: resource || undefined, target };
}
private isWorkspaceConfigurationResource(resource: URI): boolean {
private isWorkspaceConfigurationResource(resource: URI | null | undefined): boolean {
const workspace = this.contextService.getWorkspace();
return workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath;
return !!(workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath);
}
private getConfigurationFileResource(target: ConfigurationTarget, relativePath: string, resource: URI): URI {
private getConfigurationFileResource(target: ConfigurationTarget, relativePath: string, resource: URI | null | undefined): URI | null {
if (target === ConfigurationTarget.USER) {
return URI.file(this.environmentService.appSettingsPath);
}
@@ -489,7 +504,7 @@ export class ConfigurationEditingService {
if (target === ConfigurationTarget.WORKSPACE) {
if (workbenchState === WorkbenchState.WORKSPACE) {
return workspace.configuration;
return workspace.configuration || null;
}
if (workbenchState === WorkbenchState.FOLDER) {
return workspace.folders[0].toResource(relativePath);

View File

@@ -136,11 +136,11 @@ export class Configuration extends BaseConfiguration {
folders: ResourceMap<ConfigurationModel>,
memoryConfiguration: ConfigurationModel,
memoryConfigurationByResource: ResourceMap<ConfigurationModel>,
private readonly _workspace: Workspace) {
private readonly _workspace?: Workspace) {
super(defaults, user, workspaceConfiguration, folders, memoryConfiguration, memoryConfigurationByResource);
}
getValue(key: string, overrides: IConfigurationOverrides = {}): any {
getValue(key: string | undefined, overrides: IConfigurationOverrides = {}): any {
return super.getValue(key, overrides, this._workspace);
}
@@ -256,7 +256,7 @@ export class AllKeysConfigurationChangeEvent extends AbstractConfigurationChange
export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEvent {
constructor(private configurationChangeEvent: IConfigurationChangeEvent, private workspace: Workspace) { }
constructor(private configurationChangeEvent: IConfigurationChangeEvent, private workspace: Workspace | undefined) { }
get changedConfiguration(): IConfigurationModel {
return this.configurationChangeEvent.changedConfiguration;

View File

@@ -6,7 +6,6 @@
import * as nls from 'vs/nls';
import { URI } from 'vs/base/common/uri';
import * as json from 'vs/base/common/json';
import * as encoding from 'vs/base/node/encoding';
import * as strings from 'vs/base/common/strings';
import { setProperty } from 'vs/base/common/jsonEdit';
import { Queue } from 'vs/base/common/async';
@@ -17,9 +16,10 @@ import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IFileService } from 'vs/platform/files/common/files';
import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService';
import { ITextModelService, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
import { IJSONEditingService, IJSONValue, JSONEditingError, JSONEditingErrorCode } from 'vs/workbench/services/configuration/common/jsonEditing';
import { ITextModel } from 'vs/editor/common/model';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
export class JSONEditingService implements IJSONEditingService {
@@ -83,10 +83,10 @@ export class JSONEditingService implements IJSONEditingService {
return setProperty(model.getValue(), [key], value, { tabSize, insertSpaces, eol });
}
private async resolveModelReference(resource: URI): Promise<IReference<ITextEditorModel>> {
private async resolveModelReference(resource: URI): Promise<IReference<IResolvedTextEditorModel>> {
const exists = await this.fileService.existsFile(resource);
if (!exists) {
await this.fileService.updateContent(resource, '{}', { encoding: encoding.UTF8 });
await this.fileService.updateContent(resource, '{}', { encoding: 'utf8' });
}
return this.textModelResolverService.createModelReference(resource);
}
@@ -97,18 +97,18 @@ export class JSONEditingService implements IJSONEditingService {
return parseErrors.length > 0;
}
private resolveAndValidate(resource: URI, checkDirty: boolean): Promise<IReference<ITextEditorModel>> {
private resolveAndValidate(resource: URI, checkDirty: boolean): Promise<IReference<IResolvedTextEditorModel>> {
return this.resolveModelReference(resource)
.then(reference => {
const model = reference.object.textEditorModel;
if (this.hasParseErrors(model)) {
return this.reject<IReference<ITextEditorModel>>(JSONEditingErrorCode.ERROR_INVALID_FILE);
return this.reject<IReference<IResolvedTextEditorModel>>(JSONEditingErrorCode.ERROR_INVALID_FILE);
}
// Target cannot be dirty if not writing into buffer
if (checkDirty && this.textFileService.isDirty(resource)) {
return this.reject<IReference<ITextEditorModel>>(JSONEditingErrorCode.ERROR_FILE_DIRTY);
return this.reject<IReference<IResolvedTextEditorModel>>(JSONEditingErrorCode.ERROR_FILE_DIRTY);
}
return reference;
});
@@ -131,3 +131,5 @@ export class JSONEditingService implements IJSONEditingService {
}
}
}
registerSingleton(IJSONEditingService, JSONEditingService, true);

View File

@@ -5,25 +5,23 @@
import { URI } from 'vs/base/common/uri';
import { createHash } from 'crypto';
import * as paths from 'vs/base/common/paths';
import * as resources from 'vs/base/common/resources';
import { Event, Emitter } from 'vs/base/common/event';
import * as pfs from 'vs/base/node/pfs';
import * as errors from 'vs/base/common/errors';
import * as collections from 'vs/base/common/collections';
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { RunOnceScheduler, Delayer } from 'vs/base/common/async';
import { FileChangeType, FileChangesEvent, IContent, IFileService } from 'vs/platform/files/common/files';
import { isLinux } from 'vs/base/common/platform';
import { ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
import { WorkspaceConfigurationModelParser, FolderSettingsModelParser, StandaloneConfigurationModelParser } from 'vs/workbench/services/configuration/common/configurationModels';
import { FOLDER_SETTINGS_PATH, TASKS_CONFIGURATION_KEY, FOLDER_SETTINGS_NAME, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration';
import { 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 { JSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditingService';
import { WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { relative } from 'path';
import { extname, join } from 'vs/base/common/path';
import { equals } from 'vs/base/common/objects';
import { Schemas } from 'vs/base/common/network';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
@@ -37,7 +35,7 @@ export interface IWorkspaceIdentifier {
export class WorkspaceConfiguration extends Disposable {
private readonly _cachedConfiguration: CachedWorkspaceConfiguration;
private _workspaceConfiguration: IWorkspaceConfiguration | null;
private _workspaceConfiguration: IWorkspaceConfiguration;
private _workspaceIdentifier: IWorkspaceIdentifier | null = null;
private _fileService: IFileService | null = null;
@@ -99,11 +97,16 @@ export class WorkspaceConfiguration extends Disposable {
if (this._workspaceIdentifier) {
if (this._fileService) {
if (!(this._workspaceConfiguration instanceof FileServiceBasedWorkspaceConfiguration)) {
dispose(this._workspaceConfiguration);
const nodeBasedWorkspaceConfiguration = this._workspaceConfiguration instanceof NodeBasedWorkspaceConfiguration ? this._workspaceConfiguration : undefined;
this._workspaceConfiguration = new FileServiceBasedWorkspaceConfiguration(this._fileService, nodeBasedWorkspaceConfiguration);
const oldWorkspaceConfiguration = this._workspaceConfiguration;
this._workspaceConfiguration = new FileServiceBasedWorkspaceConfiguration(this._fileService, oldWorkspaceConfiguration);
this._register(this._workspaceConfiguration.onDidChange(e => this.onDidWorkspaceConfigurationChange()));
return !nodeBasedWorkspaceConfiguration;
if (oldWorkspaceConfiguration instanceof CachedWorkspaceConfiguration) {
this.updateCache();
return true;
} else {
dispose(oldWorkspaceConfiguration);
return false;
}
}
return false;
}
@@ -127,7 +130,7 @@ export class WorkspaceConfiguration extends Disposable {
private updateCache(): Promise<void> {
if (this._workspaceIdentifier && this._workspaceIdentifier.configPath.scheme !== Schemas.file && this._workspaceConfiguration instanceof FileServiceBasedWorkspaceConfiguration) {
return this._workspaceConfiguration.load(this._workspaceIdentifier)
.then(() => this._cachedConfiguration.updateWorkspace(this._workspaceIdentifier, this._workspaceConfiguration.getConfigurationModel()));
.then(() => this._cachedConfiguration.updateWorkspace(this._workspaceIdentifier!, this._workspaceConfiguration.getConfigurationModel()));
}
return Promise.resolve(undefined);
}
@@ -135,6 +138,9 @@ export class WorkspaceConfiguration extends Disposable {
interface IWorkspaceConfiguration extends IDisposable {
readonly onDidChange: Event<void>;
workspaceConfigurationModelParser: WorkspaceConfigurationModelParser;
workspaceSettings: ConfigurationModel;
workspaceIdentifier: IWorkspaceIdentifier | null;
load(workspaceIdentifier: IWorkspaceIdentifier): Promise<void>;
getConfigurationModel(): ConfigurationModel;
getFolders(): IStoredWorkspaceFolder[];
@@ -144,18 +150,18 @@ interface IWorkspaceConfiguration extends IDisposable {
abstract class AbstractWorkspaceConfiguration extends Disposable implements IWorkspaceConfiguration {
private _workspaceConfigurationModelParser: WorkspaceConfigurationModelParser;
private _workspaceSettings: ConfigurationModel;
workspaceConfigurationModelParser: WorkspaceConfigurationModelParser;
workspaceSettings: ConfigurationModel;
private _workspaceIdentifier: IWorkspaceIdentifier | null = null;
protected readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
readonly onDidChange: Event<void> = this._onDidChange.event;
constructor(from?: AbstractWorkspaceConfiguration) {
constructor(from?: IWorkspaceConfiguration) {
super();
this._workspaceConfigurationModelParser = from ? from._workspaceConfigurationModelParser : new WorkspaceConfigurationModelParser('');
this._workspaceSettings = new ConfigurationModel();
this.workspaceConfigurationModelParser = from ? from.workspaceConfigurationModelParser : new WorkspaceConfigurationModelParser('');
this.workspaceSettings = from ? from.workspaceSettings : new ConfigurationModel();
}
get workspaceIdentifier(): IWorkspaceIdentifier | null {
@@ -166,32 +172,32 @@ abstract class AbstractWorkspaceConfiguration extends Disposable implements IWor
this._workspaceIdentifier = workspaceIdentifier;
return this.loadWorkspaceConfigurationContents(workspaceIdentifier)
.then(contents => {
this._workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(workspaceIdentifier.id);
this._workspaceConfigurationModelParser.parse(contents);
this.workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(workspaceIdentifier.id);
this.workspaceConfigurationModelParser.parse(contents);
this.consolidate();
});
}
getConfigurationModel(): ConfigurationModel {
return this._workspaceConfigurationModelParser.configurationModel;
return this.workspaceConfigurationModelParser.configurationModel;
}
getFolders(): IStoredWorkspaceFolder[] {
return this._workspaceConfigurationModelParser.folders;
return this.workspaceConfigurationModelParser.folders;
}
getWorkspaceSettings(): ConfigurationModel {
return this._workspaceSettings;
return this.workspaceSettings;
}
reprocessWorkspaceSettings(): ConfigurationModel {
this._workspaceConfigurationModelParser.reprocessWorkspaceSettings();
this.workspaceConfigurationModelParser.reprocessWorkspaceSettings();
this.consolidate();
return this.getWorkspaceSettings();
}
private consolidate(): void {
this._workspaceSettings = this._workspaceConfigurationModelParser.settingsModel.merge(this._workspaceConfigurationModelParser.launchModel);
this.workspaceSettings = this.workspaceConfigurationModelParser.settingsModel.merge(this.workspaceConfigurationModelParser.launchModel);
}
protected abstract loadWorkspaceConfigurationContents(workspaceIdentifier: IWorkspaceIdentifier): Promise<string>;
@@ -214,15 +220,33 @@ class FileServiceBasedWorkspaceConfiguration extends AbstractWorkspaceConfigurat
private workspaceConfig: URI | null = null;
private readonly reloadConfigurationScheduler: RunOnceScheduler;
constructor(private fileService: IFileService, from?: AbstractWorkspaceConfiguration) {
constructor(private fileService: IFileService, from?: IWorkspaceConfiguration) {
super(from);
this.workspaceConfig = from ? from.workspaceIdentifier.configPath : null;
this.workspaceConfig = from && from.workspaceIdentifier ? from.workspaceIdentifier.configPath : null;
this._register(fileService.onFileChanges(e => this.handleWorkspaceFileEvents(e)));
this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this._onDidChange.fire(), 50));
this.watchWorkspaceConfigurationFile();
this._register(toDisposable(() => this.unWatchWorkspaceConfigurtionFile()));
}
private watchWorkspaceConfigurationFile(): void {
if (this.workspaceConfig) {
this.fileService.watchFileChanges(this.workspaceConfig);
}
}
private unWatchWorkspaceConfigurtionFile(): void {
if (this.workspaceConfig) {
this.fileService.unwatchFileChanges(this.workspaceConfig);
}
}
protected loadWorkspaceConfigurationContents(workspaceIdentifier: IWorkspaceIdentifier): Promise<string> {
this.workspaceConfig = workspaceIdentifier.configPath;
if (!(this.workspaceConfig && resources.isEqual(this.workspaceConfig, workspaceIdentifier.configPath))) {
this.unWatchWorkspaceConfigurtionFile();
this.workspaceConfig = workspaceIdentifier.configPath;
this.watchWorkspaceConfigurationFile();
}
return this.fileService.resolveContent(this.workspaceConfig)
.then(content => content.value, e => {
errors.onUnexpectedError(e);
@@ -254,39 +278,43 @@ class CachedWorkspaceConfiguration extends Disposable implements IWorkspaceConfi
private cachedWorkspacePath: string;
private cachedConfigurationPath: string;
private _workspaceConfigurationModelParser: WorkspaceConfigurationModelParser;
private _workspaceSettings: ConfigurationModel;
workspaceConfigurationModelParser: WorkspaceConfigurationModelParser;
workspaceSettings: ConfigurationModel;
constructor(private environmentService: IEnvironmentService) {
super();
this._workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser('');
this._workspaceSettings = new ConfigurationModel();
this.workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser('');
this.workspaceSettings = new ConfigurationModel();
}
load(workspaceIdentifier: IWorkspaceIdentifier): Promise<void> {
this.createPaths(workspaceIdentifier);
return pfs.readFile(this.cachedConfigurationPath)
.then(contents => {
this._workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(this.cachedConfigurationPath);
this._workspaceConfigurationModelParser.parse(contents.toString());
this._workspaceSettings = this._workspaceConfigurationModelParser.settingsModel.merge(this._workspaceConfigurationModelParser.launchModel);
}, () => null);
this.workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(this.cachedConfigurationPath);
this.workspaceConfigurationModelParser.parse(contents.toString());
this.workspaceSettings = this.workspaceConfigurationModelParser.settingsModel.merge(this.workspaceConfigurationModelParser.launchModel);
}, () => { });
}
get workspaceIdentifier(): IWorkspaceIdentifier | null {
return null;
}
getConfigurationModel(): ConfigurationModel {
return this._workspaceConfigurationModelParser.configurationModel;
return this.workspaceConfigurationModelParser.configurationModel;
}
getFolders(): IStoredWorkspaceFolder[] {
return this._workspaceConfigurationModelParser.folders;
return this.workspaceConfigurationModelParser.folders;
}
getWorkspaceSettings(): ConfigurationModel {
return this._workspaceSettings;
return this.workspaceSettings;
}
reprocessWorkspaceSettings(): ConfigurationModel {
return this._workspaceSettings;
return this.workspaceSettings;
}
async updateWorkspace(workspaceIdentifier: IWorkspaceIdentifier, configurationModel: ConfigurationModel): Promise<void> {
@@ -297,7 +325,7 @@ class CachedWorkspaceConfiguration extends Disposable implements IWorkspaceConfi
if (!exists) {
await pfs.mkdirp(this.cachedWorkspacePath);
}
const raw = JSON.stringify(configurationModel.toJSON());
const raw = JSON.stringify(configurationModel.toJSON().contents);
await pfs.writeFile(this.cachedConfigurationPath, raw);
} else {
pfs.rimraf(this.cachedWorkspacePath);
@@ -308,8 +336,8 @@ class CachedWorkspaceConfiguration extends Disposable implements IWorkspaceConfi
}
private createPaths(workspaceIdentifier: IWorkspaceIdentifier) {
this.cachedWorkspacePath = paths.join(this.environmentService.userDataPath, 'CachedConfigurations', 'workspaces', workspaceIdentifier.id);
this.cachedConfigurationPath = paths.join(this.cachedWorkspacePath, 'workspace.json');
this.cachedWorkspacePath = join(this.environmentService.userDataPath, 'CachedConfigurations', 'workspaces', workspaceIdentifier.id);
this.cachedConfigurationPath = join(this.cachedWorkspacePath, 'workspace.json');
}
}
@@ -471,7 +499,7 @@ export class FileServiceBasedFolderConfiguration extends AbstractFolderConfigura
}
private doLoadFolderConfigurationContents(): Promise<Array<{ resource: URI, value: string }>> {
const workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: Promise<IContent> } = Object.create(null);
const workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: Promise<IContent | undefined> } = Object.create(null);
const bulkContentFetchromise = Promise.resolve(this.fileService.resolveFile(this.folderConfigurationPath))
.then(stat => {
if (stat.isDirectory && stat.children) {
@@ -486,7 +514,7 @@ export class FileServiceBasedFolderConfiguration extends AbstractFolderConfigura
}
}).then(undefined, err => [] /* never fail this call */);
return bulkContentFetchromise.then(() => Promise.all(collections.values(workspaceFilePathToConfiguration)));
return bulkContentFetchromise.then(() => Promise.all<IContent>(collections.values(workspaceFilePathToConfiguration))).then(contents => contents.filter(content => content !== undefined));
}
private handleWorkspaceFileEvents(event: FileChangesEvent): void {
@@ -497,7 +525,7 @@ export class FileServiceBasedFolderConfiguration extends AbstractFolderConfigura
for (let i = 0, len = events.length; i < len; i++) {
const resource = events[i].resource;
const basename = resources.basename(resource);
const isJson = paths.extname(basename) === '.json';
const isJson = extname(basename) === '.json';
const isDeletedSettingsFolder = (events[i].type === FileChangeType.DELETED && basename === this.configFolderRelativePath);
if (!isJson && !isDeletedSettingsFolder) {
@@ -529,17 +557,11 @@ export class FileServiceBasedFolderConfiguration extends AbstractFolderConfigura
}
}
private toFolderRelativePath(resource: URI): string | null {
if (resource.scheme === Schemas.file) {
if (paths.isEqualOrParent(resource.fsPath, this.folderConfigurationPath.fsPath, !isLinux /* ignorecase */)) {
return paths.normalize(relative(this.folderConfigurationPath.fsPath, resource.fsPath));
}
} else {
if (resources.isEqualOrParent(resource, this.folderConfigurationPath)) {
return paths.normalize(relative(this.folderConfigurationPath.path, resource.path));
}
private toFolderRelativePath(resource: URI): string | undefined {
if (resources.isEqualOrParent(resource, this.folderConfigurationPath)) {
return resources.relativePath(this.folderConfigurationPath, resource);
}
return null;
return undefined;
}
}
@@ -559,8 +581,8 @@ export class CachedFolderConfiguration extends Disposable implements IFolderConf
configFolderRelativePath: string,
environmentService: IEnvironmentService) {
super();
this.cachedFolderPath = paths.join(environmentService.userDataPath, 'CachedConfigurations', 'folders', createHash('md5').update(paths.join(folder.path, configFolderRelativePath)).digest('hex'));
this.cachedConfigurationPath = paths.join(this.cachedFolderPath, 'configuration.json');
this.cachedFolderPath = join(environmentService.userDataPath, 'CachedConfigurations', 'folders', createHash('md5').update(join(folder.path, configFolderRelativePath)).digest('hex'));
this.cachedConfigurationPath = join(this.cachedFolderPath, 'configuration.json');
this.configurationModel = new ConfigurationModel();
}

View File

@@ -9,7 +9,7 @@ import { Event, Emitter } from 'vs/base/common/event';
import { ResourceMap } from 'vs/base/common/map';
import { equals, deepClone } from 'vs/base/common/objects';
import { Disposable } from 'vs/base/common/lifecycle';
import { Queue } from 'vs/base/common/async';
import { Queue, Barrier } from 'vs/base/common/async';
import { writeFile } from 'vs/base/node/pfs';
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import { IWorkspaceContextService, Workspace, WorkbenchState, IWorkspaceFolder, toWorkspaceFolders, IWorkspaceFoldersChangeEvent, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
@@ -17,34 +17,32 @@ import { isLinux } from 'vs/base/common/platform';
import { IFileService } from 'vs/platform/files/common/files';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ConfigurationChangeEvent, ConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier, isConfigurationOverrides, IConfigurationData } from 'vs/platform/configuration/common/configuration';
import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier, isConfigurationOverrides, IConfigurationData, IConfigurationService } from 'vs/platform/configuration/common/configuration';
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 { 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, IConfigurationPropertySchema, allSettings, windowSettings, resourceSettings, applicationSettings } from 'vs/platform/configuration/common/configurationRegistry';
import { IWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, isSingleFolderWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, IEmptyWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, isSingleFolderWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, IEmptyWorkspaceInitializationPayload, useSlashForPath, getStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { ICommandService } from 'vs/platform/commands/common/commands';
import product from 'vs/platform/node/product';
import product from 'vs/platform/product/node/product';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService';
import { ConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditingService';
import { WorkspaceConfiguration, FolderConfiguration } from 'vs/workbench/services/configuration/node/configuration';
import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService';
import { Schemas } from 'vs/base/common/network';
import { massageFolderPathForWorkspace } from 'vs/platform/workspaces/node/workspaces';
import { JSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditingService';
import { UserConfiguration } from 'vs/platform/configuration/node/configuration';
import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema';
import { localize } from 'vs/nls';
import { isEqual, dirname } from 'vs/base/common/resources';
import { mark } from 'vs/base/common/performance';
import { Schemas } from 'vs/base/common/network';
export class WorkspaceService extends Disposable implements IWorkspaceConfigurationService, IWorkspaceContextService {
export class WorkspaceService extends Disposable implements IConfigurationService, IWorkspaceContextService {
public _serviceBrand: any;
private workspace: Workspace;
private resolvePromise: Promise<void>;
private resolveCallback: () => void;
private completeWorkspaceBarrier: Barrier;
private _configuration: Configuration;
private defaultConfiguration: DefaultConfigurationModel;
private userConfiguration: UserConfiguration;
@@ -72,7 +70,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
constructor(private environmentService: IEnvironmentService, private workspaceSettingsRootFolder: string = FOLDER_CONFIG_FOLDER_NAME) {
super();
this.resolvePromise = new Promise(c => this.resolveCallback = c);
this.completeWorkspaceBarrier = new Barrier();
this.defaultConfiguration = new DefaultConfigurationModel();
this.userConfiguration = this._register(new UserConfiguration(environmentService.appSettingsPath));
this.workspaceConfiguration = this._register(new WorkspaceConfiguration(environmentService));
@@ -88,7 +86,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
// Workspace Context Service Impl
public getCompleteWorkspace(): Promise<Workspace> {
return this.resolvePromise.then(() => this.getWorkspace());
return this.completeWorkspaceBarrier.wait().then(() => this.getWorkspace());
}
public getWorkspace(): Workspace {
@@ -110,7 +108,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
return WorkbenchState.EMPTY;
}
public getWorkspaceFolder(resource: URI): IWorkspaceFolder {
public getWorkspaceFolder(resource: URI): IWorkspaceFolder | null {
return this.workspace.getFolder(resource);
}
@@ -154,7 +152,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
// Remove first (if any)
let currentWorkspaceFolders = this.getWorkspace().folders;
let newStoredFolders: IStoredWorkspaceFolder[] = currentWorkspaceFolders.map(f => f.raw).filter((folder, index) => {
let newStoredFolders: IStoredWorkspaceFolder[] = currentWorkspaceFolders.map(f => f.raw).filter((folder, index): folder is IStoredWorkspaceFolder => {
if (!isStoredWorkspaceFolder(folder)) {
return true; // keep entries which are unrelated
}
@@ -162,44 +160,26 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
return !this.contains(foldersToRemove, currentWorkspaceFolders[index].uri); // keep entries which are unrelated
});
const slashForPath = useSlashForPath(newStoredFolders);
foldersHaveChanged = currentWorkspaceFolders.length !== newStoredFolders.length;
// Add afterwards (if any)
if (foldersToAdd.length) {
// Recompute current workspace folders if we have folders to add
const workspaceConfigFolder = dirname(this.getWorkspace().configuration);
const workspaceConfigFolder = dirname(this.getWorkspace().configuration!);
currentWorkspaceFolders = toWorkspaceFolders(newStoredFolders, workspaceConfigFolder);
const currentWorkspaceFolderUris = currentWorkspaceFolders.map(folder => folder.uri);
const storedFoldersToAdd: IStoredWorkspaceFolder[] = [];
foldersToAdd.forEach(folderToAdd => {
if (this.contains(currentWorkspaceFolderUris, folderToAdd.uri)) {
const folderURI = folderToAdd.uri;
if (this.contains(currentWorkspaceFolderUris, folderURI)) {
return; // already existing
}
let storedFolder: IStoredWorkspaceFolder;
// File resource: use "path" property
if (folderToAdd.uri.scheme === Schemas.file) {
storedFolder = {
path: massageFolderPathForWorkspace(folderToAdd.uri.fsPath, workspaceConfigFolder, newStoredFolders)
};
}
// Any other resource: use "uri" property
else {
storedFolder = {
uri: folderToAdd.uri.toString(true)
};
}
if (folderToAdd.name) {
storedFolder.name = folderToAdd.name;
}
storedFoldersToAdd.push(storedFolder);
storedFoldersToAdd.push(getStoredWorkspaceFolder(folderURI, folderToAdd.name, workspaceConfigFolder, slashForPath));
});
// Apply to array of newStoredFolders
@@ -266,7 +246,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
const overrides = isConfigurationOverrides(arg3) ? arg3 : undefined;
const target = this.deriveConfigurationTarget(key, value, overrides, overrides ? arg4 : arg3);
return target ? this.writeConfigurationValue(key, value, target, overrides, donotNotifyError)
: Promise.resolve(null);
: Promise.resolve();
}
reloadConfiguration(folder?: IWorkspaceFolder, key?: string): Promise<void> {
@@ -324,7 +304,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
for (const workspaceFolder of changedWorkspaceFolders) {
this.onWorkspaceFolderConfigurationChanged(workspaceFolder);
}
this.resolveCallback();
this.releaseWorkspaceBarrier();
});
}
@@ -346,12 +326,16 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
}
private createMultiFolderWorkspace(workspaceIdentifier: IWorkspaceIdentifier): Promise<Workspace> {
return this.workspaceConfiguration.load({ id: workspaceIdentifier.id, configPath: URI.file(workspaceIdentifier.configPath) })
return this.workspaceConfiguration.load({ id: workspaceIdentifier.id, configPath: workspaceIdentifier.configPath })
.then(() => {
const workspaceConfigPath = URI.file(workspaceIdentifier.configPath);
const workspaceConfigPath = workspaceIdentifier.configPath;
const workspaceFolders = toWorkspaceFolders(this.workspaceConfiguration.getFolders(), dirname(workspaceConfigPath));
const workspaceId = workspaceIdentifier.id;
return new Workspace(workspaceId, workspaceFolders, workspaceConfigPath);
const workspace = new Workspace(workspaceId, workspaceFolders, workspaceConfigPath);
if (workspace.configuration!.scheme === Schemas.file) {
this.releaseWorkspaceBarrier(); // Release barrier as workspace is complete because it is from disk.
}
return workspace;
});
}
@@ -365,17 +349,27 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
configuredFolders = [{ uri: folder.toString() }];
}
return Promise.resolve(new Workspace(singleFolder.id, toWorkspaceFolders(configuredFolders)));
const workspace = new Workspace(singleFolder.id, toWorkspaceFolders(configuredFolders));
this.releaseWorkspaceBarrier(); // Release barrier as workspace is complete because it is single folder.
return Promise.resolve(workspace);
}
private createEmptyWorkspace(emptyWorkspace: IEmptyWorkspaceInitializationPayload): Promise<Workspace> {
return Promise.resolve(new Workspace(emptyWorkspace.id));
const workspace = new Workspace(emptyWorkspace.id);
this.releaseWorkspaceBarrier(); // Release barrier as workspace is complete because it is an empty workspace.
return Promise.resolve(workspace);
}
private releaseWorkspaceBarrier(): void {
if (!this.completeWorkspaceBarrier.isOpen()) {
this.completeWorkspaceBarrier.open();
}
}
private updateWorkspaceAndInitializeConfiguration(workspace: Workspace, postInitialisationTask: () => void): Promise<void> {
const hasWorkspaceBefore = !!this.workspace;
let previousState: WorkbenchState;
let previousWorkspacePath: string;
let previousWorkspacePath: string | undefined;
let previousFolders: WorkspaceFolder[];
if (hasWorkspaceBefore) {
@@ -467,7 +461,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
folderConfigurations.forEach((folderConfiguration, index) => folderConfigurationModels.set(folders[index].uri, folderConfiguration));
const currentConfiguration = this._configuration;
this._configuration = new Configuration(this.defaultConfiguration, userConfigurationModel, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new ResourceMap<ConfigurationModel>(), this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: Sandy Avoid passing null
this._configuration = new Configuration(this.defaultConfiguration, userConfigurationModel, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new ResourceMap<ConfigurationModel>(), this.workspace);
if (currentConfiguration) {
const changedKeys = this._configuration.compare(currentConfiguration);
@@ -495,10 +489,10 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
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());
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.workspace.folders.forEach(folder => this._configuration.updateFolderConfiguration(folder.uri, this.cachedFolderConfigs.get(folder.uri)!.reprocess()));
}
this.triggerConfigurationChange(new ConfigurationChangeEvent().change(keys), ConfigurationTarget.DEFAULT);
}
@@ -578,7 +572,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]) {
const folderConfiguration = this.cachedFolderConfigs.get(key);
folderConfiguration.dispose();
folderConfiguration!.dispose();
this.cachedFolderConfigs.delete(key);
changeEvent = changeEvent.change(this._configuration.compareAndDeleteFolderConfiguration(key));
}
@@ -609,14 +603,14 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
})]);
}
private writeConfigurationValue(key: string, value: any, target: ConfigurationTarget, overrides: IConfigurationOverrides, donotNotifyError: boolean): Promise<void> {
private writeConfigurationValue(key: string, value: any, target: ConfigurationTarget, overrides: IConfigurationOverrides | undefined, donotNotifyError: boolean): Promise<void> {
if (target === ConfigurationTarget.DEFAULT) {
return Promise.reject(new Error('Invalid configuration target'));
}
if (target === ConfigurationTarget.MEMORY) {
this._configuration.updateValue(key, value, overrides);
this.triggerConfigurationChange(new ConfigurationChangeEvent().change(overrides.overrideIdentifier ? [keyFromOverrideIdentifier(overrides.overrideIdentifier)] : [key], overrides.resource), target);
this.triggerConfigurationChange(new ConfigurationChangeEvent().change(overrides && overrides.overrideIdentifier ? [keyFromOverrideIdentifier(overrides.overrideIdentifier)] : [key], overrides && overrides.resource || undefined), target);
return Promise.resolve(undefined);
}
@@ -624,20 +618,20 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
.then(() => {
switch (target) {
case ConfigurationTarget.USER:
return this.reloadUserConfiguration();
return this.reloadUserConfiguration().then(_ => Promise.resolve());
case ConfigurationTarget.WORKSPACE:
return this.reloadWorkspaceConfiguration();
case ConfigurationTarget.WORKSPACE_FOLDER:
const workspaceFolder = overrides && overrides.resource ? this.workspace.getFolder(overrides.resource) : null;
if (workspaceFolder) {
return this.reloadWorkspaceFolderConfiguration(this.workspace.getFolder(overrides.resource), key).then(() => null);
return this.reloadWorkspaceFolderConfiguration(workspaceFolder, key);
}
}
return null;
return Promise.resolve();
});
}
private deriveConfigurationTarget(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): ConfigurationTarget {
private deriveConfigurationTarget(key: string, value: any, overrides: IConfigurationOverrides | undefined, target: ConfigurationTarget): ConfigurationTarget | undefined {
if (target) {
return target;
}
@@ -688,7 +682,7 @@ interface IExportedConfigurationNode {
name: string;
description: string;
default: any;
type: string | string[];
type?: string | string[];
enum?: any[];
enumDescriptions?: string[];
}
@@ -696,8 +690,8 @@ interface IExportedConfigurationNode {
interface IConfigurationExport {
settings: IExportedConfigurationNode[];
buildTime: number;
commit: string;
buildNumber: number;
commit?: string;
buildNumber?: number;
}
export class DefaultConfigurationExportHelper {

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { join } from 'vs/base/common/paths';
import { join } from 'vs/base/common/path';
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';

View File

@@ -6,7 +6,7 @@
import * as sinon from 'sinon';
import * as assert from 'assert';
import * as os from 'os';
import * as path from 'path';
import * as path from 'vs/base/common/path';
import * as fs from 'fs';
import * as json from 'vs/base/common/json';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -20,8 +20,8 @@ import { TestNotificationService } from 'vs/platform/notification/test/common/te
import * as uuid from 'vs/base/common/uuid';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService';
import { FileService } from 'vs/workbench/services/files/electron-browser/fileService';
import { ConfigurationEditingService, ConfigurationEditingError, ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/node/configurationEditingService';
import { FileService } from 'vs/workbench/services/files/node/fileService';
import { ConfigurationEditingService, ConfigurationEditingError, ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/common/configurationEditingService';
import { IFileService } from 'vs/platform/files/common/files';
import { WORKSPACE_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';

View File

@@ -6,7 +6,7 @@
import * as assert from 'assert';
import * as sinon from 'sinon';
import * as fs from 'fs';
import * as path from 'path';
import * as path from 'vs/base/common/path';
import * as os from 'os';
import { URI } from 'vs/base/common/uri';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -18,23 +18,25 @@ import * as uuid from 'vs/base/common/uuid';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService';
import { ISingleFolderWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces';
import { ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/node/configurationEditingService';
import { ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/common/configurationEditingService';
import { IFileService, FileChangesEvent, FileChangeType } from 'vs/platform/files/common/files';
import { IWorkspaceContextService, WorkbenchState, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace';
import { ConfigurationTarget, IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
import { workbenchInstantiationService, TestTextResourceConfigurationService, TestTextFileService, TestLifecycleService, TestEnvironmentService, TestStorageService } from 'vs/workbench/test/workbenchTestServices';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
import { FileService } from 'vs/workbench/services/files/electron-browser/fileService';
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';
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 { Uri } from 'vscode';
import { JSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditingService';
import { createHash } from 'crypto';
import { Emitter, Event } from 'vs/base/common/event';
import { Schemas } from 'vs/base/common/network';
import { originalFSPath } from 'vs/base/common/resources';
import { isLinux } from 'vs/base/common/platform';
import { IWorkspaceIdentifier } from 'vs/workbench/services/configuration/node/configuration';
class SettingsTestEnvironmentService extends EnvironmentService {
@@ -58,14 +60,14 @@ function setUpFolder(folderName: string, parentDir: string): Promise<string> {
return Promise.resolve(pfs.mkdirp(workspaceSettingsDir, 493).then(() => folderDir));
}
function convertToWorkspacePayload(folder: Uri): ISingleFolderWorkspaceInitializationPayload {
function convertToWorkspacePayload(folder: URI): ISingleFolderWorkspaceInitializationPayload {
return {
id: createHash('md5').update(folder.fsPath).digest('hex'),
folder
} as ISingleFolderWorkspaceInitializationPayload;
}
function setUpWorkspace(folders: string[]): Promise<{ parentDir: string, configPath: string }> {
function setUpWorkspace(folders: string[]): Promise<{ parentDir: string, configPath: URI }> {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
@@ -77,7 +79,7 @@ function setUpWorkspace(folders: string[]): Promise<{ parentDir: string, configP
fs.writeFileSync(configPath, JSON.stringify(workspace, null, '\t'));
return Promise.all(folders.map(folder => setUpFolder(folder, parentDir)))
.then(() => ({ parentDir, configPath }));
.then(() => ({ parentDir, configPath: URI.file(configPath) }));
}));
}
@@ -89,3 +91,19 @@ suite('WorkspaceContextService - Folder', () => {
assert.equal(0, 0);
});
});
function getWorkspaceId(configPath: URI): string {
let workspaceConfigPath = configPath.scheme === Schemas.file ? originalFSPath(configPath) : configPath.toString();
if (!isLinux) {
workspaceConfigPath = workspaceConfigPath.toLowerCase(); // sanitize for platform file system
}
return createHash('md5').update(workspaceConfigPath).digest('hex');
}
export function getWorkspaceIdentifier(configPath: URI): IWorkspaceIdentifier {
return {
configPath,
id: getWorkspaceId(configPath)
};
}