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:
Karl Burtram
2018-01-28 23:37:17 -08:00
committed by GitHub
parent 9a1ac20710
commit 251ae01c3e
8009 changed files with 93378 additions and 35634 deletions

View File

@@ -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;

View File

@@ -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];
}

View File

@@ -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(),

View File

@@ -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.");
};
}
}
}
}