mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-30 00:30:29 -04:00
Merge from vscode 591842cc4b71958c81947b254924a215fe3edcbd (#4886)
This commit is contained in:
@@ -9,7 +9,7 @@ import { Event, Emitter } from 'vs/base/common/event';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { Disposable, IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { FileChangeType, FileChangesEvent, IFileService } from 'vs/platform/files/common/files';
|
||||
import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files';
|
||||
import { ConfigurationModel, ConfigurationModelParser } 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, IConfigurationCache, ConfigurationKey, IConfigurationFileService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
@@ -22,67 +22,36 @@ import { equals } from 'vs/base/common/objects';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IConfigurationModel, compare } from 'vs/platform/configuration/common/configuration';
|
||||
import { createSHA1 } from 'vs/base/browser/hash';
|
||||
|
||||
export class LocalUserConfiguration extends Disposable {
|
||||
|
||||
private readonly userConfigurationResource: URI;
|
||||
private userConfiguration: NodeBasedUserConfiguration | FileServiceBasedUserConfiguration;
|
||||
private changeDisposable: IDisposable = Disposable.None;
|
||||
|
||||
private readonly _onDidChangeConfiguration: Emitter<ConfigurationModel> = this._register(new Emitter<ConfigurationModel>());
|
||||
public readonly onDidChangeConfiguration: Event<ConfigurationModel> = this._onDidChangeConfiguration.event;
|
||||
|
||||
constructor(
|
||||
userConfigurationResource: URI,
|
||||
configurationFileService: IConfigurationFileService
|
||||
) {
|
||||
super();
|
||||
this.userConfigurationResource = userConfigurationResource;
|
||||
this.userConfiguration = this._register(new NodeBasedUserConfiguration(this.userConfigurationResource, configurationFileService));
|
||||
}
|
||||
|
||||
initialize(): Promise<ConfigurationModel> {
|
||||
return this.userConfiguration.initialize();
|
||||
}
|
||||
|
||||
reload(): Promise<ConfigurationModel> {
|
||||
return this.userConfiguration.reload();
|
||||
}
|
||||
|
||||
async adopt(fileService: IFileService): Promise<ConfigurationModel | null> {
|
||||
if (this.userConfiguration instanceof NodeBasedUserConfiguration) {
|
||||
const oldConfigurationModel = this.userConfiguration.getConfigurationModel();
|
||||
this.userConfiguration.dispose();
|
||||
dispose(this.changeDisposable);
|
||||
|
||||
let newConfigurationModel = new ConfigurationModel();
|
||||
this.userConfiguration = this._register(new FileServiceBasedUserConfiguration(this.userConfigurationResource, fileService));
|
||||
this.changeDisposable = this._register(this.userConfiguration.onDidChangeConfiguration(configurationModel => this._onDidChangeConfiguration.fire(configurationModel)));
|
||||
newConfigurationModel = await this.userConfiguration.initialize();
|
||||
|
||||
const { added, updated, removed } = compare(oldConfigurationModel, newConfigurationModel);
|
||||
if (added.length > 0 || updated.length > 0 || removed.length > 0) {
|
||||
return newConfigurationModel;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
|
||||
export class RemoteUserConfiguration extends Disposable {
|
||||
|
||||
private readonly _cachedConfiguration: CachedUserConfiguration;
|
||||
private _userConfiguration: FileServiceBasedUserConfiguration | CachedUserConfiguration;
|
||||
private readonly _configurationFileService: IConfigurationFileService;
|
||||
private _userConfiguration: UserConfiguration | CachedUserConfiguration;
|
||||
private _userConfigurationDisposable: IDisposable = Disposable.None;
|
||||
|
||||
private readonly _onDidChangeConfiguration: Emitter<ConfigurationModel> = this._register(new Emitter<ConfigurationModel>());
|
||||
public readonly onDidChangeConfiguration: Event<ConfigurationModel> = this._onDidChangeConfiguration.event;
|
||||
|
||||
constructor(
|
||||
remoteAuthority: string,
|
||||
configurationCache: IConfigurationCache
|
||||
configurationCache: IConfigurationCache,
|
||||
configurationFileService: IConfigurationFileService,
|
||||
remoteAgentService: IRemoteAgentService
|
||||
) {
|
||||
super();
|
||||
this._configurationFileService = configurationFileService;
|
||||
this._userConfiguration = this._cachedConfiguration = new CachedUserConfiguration(remoteAuthority, configurationCache);
|
||||
remoteAgentService.getEnvironment().then(environment => {
|
||||
if (environment) {
|
||||
this._userConfiguration.dispose();
|
||||
this._userConfigurationDisposable.dispose();
|
||||
this._userConfiguration = this._register(new UserConfiguration(environment.appSettingsPath, this._configurationFileService));
|
||||
this._userConfigurationDisposable = this._register(this._userConfiguration.onDidChangeConfiguration(configurationModel => this.onDidUserConfigurationChange(configurationModel)));
|
||||
this._userConfiguration.initialize().then(configurationModel => this.onDidUserConfigurationChange(configurationModel));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
initialize(): Promise<ConfigurationModel> {
|
||||
@@ -93,24 +62,6 @@ export class RemoteUserConfiguration extends Disposable {
|
||||
return this._userConfiguration.reload();
|
||||
}
|
||||
|
||||
async adopt(configurationResource: URI | null, fileService: IFileService): Promise<ConfigurationModel | null> {
|
||||
if (this._userConfiguration instanceof CachedUserConfiguration) {
|
||||
const oldConfigurationModel = this._userConfiguration.getConfigurationModel();
|
||||
let newConfigurationModel = new ConfigurationModel();
|
||||
if (configurationResource) {
|
||||
this._userConfiguration = new FileServiceBasedUserConfiguration(configurationResource, fileService);
|
||||
this._register(this._userConfiguration.onDidChangeConfiguration(configurationModel => this.onDidUserConfigurationChange(configurationModel)));
|
||||
newConfigurationModel = await this._userConfiguration.initialize();
|
||||
}
|
||||
const { added, updated, removed } = compare(oldConfigurationModel, newConfigurationModel);
|
||||
if (added.length > 0 || updated.length > 0 || removed.length > 0) {
|
||||
this.updateCache(newConfigurationModel);
|
||||
return newConfigurationModel;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private onDidUserConfigurationChange(configurationModel: ConfigurationModel): void {
|
||||
this.updateCache(configurationModel);
|
||||
this._onDidChangeConfiguration.fire(configurationModel);
|
||||
@@ -121,51 +72,7 @@ export class RemoteUserConfiguration extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
class NodeBasedUserConfiguration extends Disposable {
|
||||
|
||||
private configuraitonModel: ConfigurationModel = new ConfigurationModel();
|
||||
|
||||
constructor(
|
||||
private readonly userConfigurationResource: URI,
|
||||
private readonly configurationFileService: IConfigurationFileService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
initialize(): Promise<ConfigurationModel> {
|
||||
return this._load();
|
||||
}
|
||||
|
||||
reload(): Promise<ConfigurationModel> {
|
||||
return this._load();
|
||||
}
|
||||
|
||||
getConfigurationModel(): ConfigurationModel {
|
||||
return this.configuraitonModel;
|
||||
}
|
||||
|
||||
async _load(): Promise<ConfigurationModel> {
|
||||
const exists = await this.configurationFileService.exists(this.userConfigurationResource);
|
||||
if (exists) {
|
||||
try {
|
||||
const content = await this.configurationFileService.resolveContent(this.userConfigurationResource);
|
||||
const parser = new ConfigurationModelParser(this.userConfigurationResource.toString());
|
||||
parser.parse(content);
|
||||
this.configuraitonModel = parser.configurationModel;
|
||||
} catch (e) {
|
||||
// ignore error
|
||||
errors.onUnexpectedError(e);
|
||||
this.configuraitonModel = new ConfigurationModel();
|
||||
}
|
||||
} else {
|
||||
this.configuraitonModel = new ConfigurationModel();
|
||||
}
|
||||
return this.configuraitonModel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class FileServiceBasedUserConfiguration extends Disposable {
|
||||
export class UserConfiguration extends Disposable {
|
||||
|
||||
private readonly reloadConfigurationScheduler: RunOnceScheduler;
|
||||
protected readonly _onDidChangeConfiguration: Emitter<ConfigurationModel> = this._register(new Emitter<ConfigurationModel>());
|
||||
@@ -176,11 +83,11 @@ export class FileServiceBasedUserConfiguration extends Disposable {
|
||||
|
||||
constructor(
|
||||
private readonly configurationResource: URI,
|
||||
private readonly fileService: IFileService
|
||||
private readonly configurationFileService: IConfigurationFileService
|
||||
) {
|
||||
super();
|
||||
|
||||
this._register(fileService.onFileChanges(e => this.handleFileEvents(e)));
|
||||
this._register(configurationFileService.onFileChanges(e => this.handleFileEvents(e)));
|
||||
this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.reload().then(configurationModel => this._onDidChangeConfiguration.fire(configurationModel)), 50));
|
||||
this._register(toDisposable(() => {
|
||||
this.stopWatchingResource();
|
||||
@@ -189,7 +96,7 @@ export class FileServiceBasedUserConfiguration extends Disposable {
|
||||
}
|
||||
|
||||
private watchResource(): void {
|
||||
this.fileWatcherDisposable = this.fileService.watch(this.configurationResource);
|
||||
this.fileWatcherDisposable = this.configurationFileService.watch(this.configurationResource);
|
||||
}
|
||||
|
||||
private stopWatchingResource(): void {
|
||||
@@ -199,7 +106,7 @@ export class FileServiceBasedUserConfiguration extends Disposable {
|
||||
|
||||
private watchDirectory(): void {
|
||||
const directory = resources.dirname(this.configurationResource);
|
||||
this.directoryWatcherDisposable = this.fileService.watch(directory);
|
||||
this.directoryWatcherDisposable = this.configurationFileService.watch(directory);
|
||||
}
|
||||
|
||||
private stopWatchingDirectory(): void {
|
||||
@@ -208,22 +115,34 @@ export class FileServiceBasedUserConfiguration extends Disposable {
|
||||
}
|
||||
|
||||
async initialize(): Promise<ConfigurationModel> {
|
||||
const exists = await this.fileService.exists(this.configurationResource);
|
||||
const exists = await this.configurationFileService.exists(this.configurationResource);
|
||||
this.onResourceExists(exists);
|
||||
return this.reload();
|
||||
const configuraitonModel = await this.reload();
|
||||
if (!this.configurationFileService.isWatching) {
|
||||
this.configurationFileService.whenWatchingStarted.then(() => this.onWatchStarted(configuraitonModel));
|
||||
}
|
||||
return configuraitonModel;
|
||||
}
|
||||
|
||||
async reload(): Promise<ConfigurationModel> {
|
||||
try {
|
||||
const content = await this.fileService.resolveContent(this.configurationResource);
|
||||
const content = await this.configurationFileService.resolveContent(this.configurationResource);
|
||||
const parser = new ConfigurationModelParser(this.configurationResource.toString());
|
||||
parser.parse(content.value);
|
||||
parser.parse(content);
|
||||
return parser.configurationModel;
|
||||
} catch (e) {
|
||||
return new ConfigurationModel();
|
||||
}
|
||||
}
|
||||
|
||||
private async onWatchStarted(currentModel: ConfigurationModel): Promise<void> {
|
||||
const configuraitonModel = await this.reload();
|
||||
const { added, removed, updated } = compare(currentModel, configuraitonModel);
|
||||
if (added.length || removed.length || updated.length) {
|
||||
this._onDidChangeConfiguration.fire(configuraitonModel);
|
||||
}
|
||||
}
|
||||
|
||||
private async handleFileEvents(event: FileChangesEvent): Promise<void> {
|
||||
const events = event.changes;
|
||||
|
||||
@@ -304,41 +223,38 @@ class CachedUserConfiguration extends Disposable {
|
||||
|
||||
export class WorkspaceConfiguration extends Disposable {
|
||||
|
||||
private readonly _cachedConfiguration: CachedWorkspaceConfiguration;
|
||||
private readonly _configurationFileService: IConfigurationFileService;
|
||||
private readonly _cachedConfiguration: CachedWorkspaceConfiguration;
|
||||
private _workspaceConfiguration: IWorkspaceConfiguration;
|
||||
private _workspaceConfigurationChangeDisposable: IDisposable = Disposable.None;
|
||||
private _workspaceIdentifier: IWorkspaceIdentifier | null = null;
|
||||
private _fileService: IFileService | null = null;
|
||||
|
||||
private readonly _onDidUpdateConfiguration: Emitter<void> = this._register(new Emitter<void>());
|
||||
public readonly onDidUpdateConfiguration: Event<void> = this._onDidUpdateConfiguration.event;
|
||||
|
||||
private _loaded: boolean = false;
|
||||
get loaded(): boolean { return this._loaded; }
|
||||
|
||||
constructor(
|
||||
configurationCache: IConfigurationCache,
|
||||
configurationFileService: IConfigurationFileService
|
||||
) {
|
||||
super();
|
||||
this._cachedConfiguration = new CachedWorkspaceConfiguration(configurationCache);
|
||||
this._configurationFileService = configurationFileService;
|
||||
this._workspaceConfiguration = this._cachedConfiguration;
|
||||
this._workspaceConfiguration = this._cachedConfiguration = new CachedWorkspaceConfiguration(configurationCache);
|
||||
}
|
||||
|
||||
adopt(fileService: IFileService): Promise<boolean> {
|
||||
if (!this._fileService) {
|
||||
this._fileService = fileService;
|
||||
if (this.adoptWorkspaceConfiguration()) {
|
||||
if (this._workspaceIdentifier) {
|
||||
return this._workspaceConfiguration.load(this._workspaceIdentifier).then(() => true);
|
||||
}
|
||||
async load(workspaceIdentifier: IWorkspaceIdentifier): Promise<void> {
|
||||
this._workspaceIdentifier = workspaceIdentifier;
|
||||
if (!(this._workspaceConfiguration instanceof FileServiceBasedWorkspaceConfiguration)) {
|
||||
if (this._workspaceIdentifier.configPath.scheme === Schemas.file) {
|
||||
this.switch();
|
||||
} else {
|
||||
this.waitAndSwitch(this._workspaceIdentifier);
|
||||
}
|
||||
}
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
load(workspaceIdentifier: IWorkspaceIdentifier): Promise<void> {
|
||||
this._workspaceIdentifier = workspaceIdentifier;
|
||||
this.adoptWorkspaceConfiguration();
|
||||
return this._workspaceConfiguration.load(this._workspaceIdentifier);
|
||||
await this._workspaceConfiguration.load(this._workspaceIdentifier);
|
||||
this._loaded = this._workspaceConfiguration instanceof FileServiceBasedWorkspaceConfiguration;
|
||||
}
|
||||
|
||||
reload(): Promise<void> {
|
||||
@@ -366,38 +282,26 @@ export class WorkspaceConfiguration extends Disposable {
|
||||
return this.getConfiguration();
|
||||
}
|
||||
|
||||
private adoptWorkspaceConfiguration(): boolean {
|
||||
if (this._workspaceIdentifier) {
|
||||
if (this._fileService) {
|
||||
if (!(this._workspaceConfiguration instanceof FileServiceBasedWorkspaceConfiguration)) {
|
||||
const oldWorkspaceConfiguration = this._workspaceConfiguration;
|
||||
this._workspaceConfiguration = new FileServiceBasedWorkspaceConfiguration(this._fileService, oldWorkspaceConfiguration);
|
||||
this._register(this._workspaceConfiguration.onDidChange(e => this.onDidWorkspaceConfigurationChange()));
|
||||
if (oldWorkspaceConfiguration instanceof CachedWorkspaceConfiguration) {
|
||||
this.updateCache();
|
||||
return true;
|
||||
} else {
|
||||
dispose(oldWorkspaceConfiguration);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (this._workspaceIdentifier.configPath.scheme === Schemas.file) {
|
||||
if (!(this._workspaceConfiguration instanceof NodeBasedWorkspaceConfiguration)) {
|
||||
dispose(this._workspaceConfiguration);
|
||||
this._workspaceConfiguration = new NodeBasedWorkspaceConfiguration(this._configurationFileService);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private async waitAndSwitch(workspaceIdentifier: IWorkspaceIdentifier): Promise<void> {
|
||||
await this._configurationFileService.whenProviderRegistered(workspaceIdentifier.configPath.scheme);
|
||||
if (!(this._workspaceConfiguration instanceof FileServiceBasedWorkspaceConfiguration)) {
|
||||
this.switch();
|
||||
this._loaded = true;
|
||||
this.onDidWorkspaceConfigurationChange();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private onDidWorkspaceConfigurationChange(): void {
|
||||
private switch(): void {
|
||||
this._workspaceConfiguration.dispose();
|
||||
this._workspaceConfigurationChangeDisposable.dispose();
|
||||
this._workspaceConfiguration = this._register(new FileServiceBasedWorkspaceConfiguration(this._configurationFileService));
|
||||
this._workspaceConfigurationChangeDisposable = this._register(this._workspaceConfiguration.onDidChange(e => this.onDidWorkspaceConfigurationChange()));
|
||||
}
|
||||
|
||||
private async onDidWorkspaceConfigurationChange(): Promise<void> {
|
||||
await this.reload();
|
||||
this.updateCache();
|
||||
this.reload().then(() => this._onDidUpdateConfiguration.fire());
|
||||
this._onDidUpdateConfiguration.fire();
|
||||
}
|
||||
|
||||
private updateCache(): Promise<void> {
|
||||
@@ -421,20 +325,30 @@ interface IWorkspaceConfiguration extends IDisposable {
|
||||
reprocessWorkspaceSettings(): ConfigurationModel;
|
||||
}
|
||||
|
||||
abstract class AbstractWorkspaceConfiguration extends Disposable implements IWorkspaceConfiguration {
|
||||
class FileServiceBasedWorkspaceConfiguration extends Disposable implements IWorkspaceConfiguration {
|
||||
|
||||
workspaceConfigurationModelParser: WorkspaceConfigurationModelParser;
|
||||
workspaceSettings: ConfigurationModel;
|
||||
private _workspaceIdentifier: IWorkspaceIdentifier | null = null;
|
||||
private workspaceConfigWatcher: IDisposable;
|
||||
private readonly reloadConfigurationScheduler: RunOnceScheduler;
|
||||
|
||||
protected readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChange: Event<void> = this._onDidChange.event;
|
||||
|
||||
constructor(from?: IWorkspaceConfiguration) {
|
||||
constructor(private configurationFileService: IConfigurationFileService) {
|
||||
super();
|
||||
|
||||
this.workspaceConfigurationModelParser = from ? from.workspaceConfigurationModelParser : new WorkspaceConfigurationModelParser('');
|
||||
this.workspaceSettings = from ? from.workspaceSettings : new ConfigurationModel();
|
||||
this.workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser('');
|
||||
this.workspaceSettings = new ConfigurationModel();
|
||||
|
||||
this._register(configurationFileService.onFileChanges(e => this.handleWorkspaceFileEvents(e)));
|
||||
this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this._onDidChange.fire(), 50));
|
||||
this.workspaceConfigWatcher = this._register(this.watchWorkspaceConfigurationFile());
|
||||
|
||||
if (!this.configurationFileService.isWatching) {
|
||||
this.configurationFileService.whenWatchingStarted.then(() => this.onWatchStarted());
|
||||
}
|
||||
}
|
||||
|
||||
get workspaceIdentifier(): IWorkspaceIdentifier | null {
|
||||
@@ -442,13 +356,20 @@ abstract class AbstractWorkspaceConfiguration extends Disposable implements IWor
|
||||
}
|
||||
|
||||
async load(workspaceIdentifier: IWorkspaceIdentifier): Promise<void> {
|
||||
this._workspaceIdentifier = workspaceIdentifier;
|
||||
this.workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(workspaceIdentifier.id);
|
||||
if (!this._workspaceIdentifier || this._workspaceIdentifier.id !== workspaceIdentifier.id) {
|
||||
this._workspaceIdentifier = workspaceIdentifier;
|
||||
this.workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(this._workspaceIdentifier.id);
|
||||
dispose(this.workspaceConfigWatcher);
|
||||
this.workspaceConfigWatcher = this._register(this.watchWorkspaceConfigurationFile());
|
||||
}
|
||||
let contents = '';
|
||||
try {
|
||||
contents = (await this.loadWorkspaceConfigurationContents(workspaceIdentifier.configPath)) || '';
|
||||
} catch (e) {
|
||||
errors.onUnexpectedError(e);
|
||||
contents = await this.configurationFileService.resolveContent(this._workspaceIdentifier.configPath);
|
||||
} catch (error) {
|
||||
const exists = await this.configurationFileService.exists(this._workspaceIdentifier.configPath);
|
||||
if (exists) {
|
||||
errors.onUnexpectedError(error);
|
||||
}
|
||||
}
|
||||
this.workspaceConfigurationModelParser.parse(contents);
|
||||
this.consolidate();
|
||||
@@ -472,69 +393,34 @@ abstract class AbstractWorkspaceConfiguration extends Disposable implements IWor
|
||||
return this.getWorkspaceSettings();
|
||||
}
|
||||
|
||||
private async onWatchStarted(): Promise<void> {
|
||||
if (this.workspaceIdentifier) {
|
||||
const currentModel = this.getConfigurationModel();
|
||||
await this.load(this.workspaceIdentifier);
|
||||
const newModel = this.getConfigurationModel();
|
||||
const { added, removed, updated } = compare(currentModel, newModel);
|
||||
if (added.length || removed.length || updated.length) {
|
||||
this._onDidChange.fire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private consolidate(): void {
|
||||
this.workspaceSettings = this.workspaceConfigurationModelParser.settingsModel.merge(this.workspaceConfigurationModelParser.launchModel);
|
||||
}
|
||||
|
||||
protected abstract loadWorkspaceConfigurationContents(workspaceConfigurationResource: URI): Promise<string | undefined>;
|
||||
}
|
||||
|
||||
class NodeBasedWorkspaceConfiguration extends AbstractWorkspaceConfiguration {
|
||||
|
||||
constructor(private readonly configurationFileService: IConfigurationFileService) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async loadWorkspaceConfigurationContents(workspaceConfigurationResource: URI): Promise<string | undefined> {
|
||||
const exists = await this.configurationFileService.exists(workspaceConfigurationResource);
|
||||
if (exists) {
|
||||
return this.configurationFileService.resolveContent(workspaceConfigurationResource);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class FileServiceBasedWorkspaceConfiguration extends AbstractWorkspaceConfiguration {
|
||||
|
||||
private workspaceConfig: URI | null = null;
|
||||
private workspaceConfigWatcher: IDisposable;
|
||||
|
||||
private readonly reloadConfigurationScheduler: RunOnceScheduler;
|
||||
|
||||
constructor(private fileService: IFileService, from?: IWorkspaceConfiguration) {
|
||||
super(from);
|
||||
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.workspaceConfigWatcher = this.watchWorkspaceConfigurationFile();
|
||||
}
|
||||
|
||||
private watchWorkspaceConfigurationFile(): IDisposable {
|
||||
if (this.workspaceConfig) {
|
||||
return this.fileService.watch(this.workspaceConfig);
|
||||
}
|
||||
|
||||
return Disposable.None;
|
||||
}
|
||||
|
||||
protected loadWorkspaceConfigurationContents(workspaceConfigurationResource: URI): Promise<string> {
|
||||
if (!(this.workspaceConfig && resources.isEqual(this.workspaceConfig, workspaceConfigurationResource))) {
|
||||
dispose(this.workspaceConfigWatcher);
|
||||
this.workspaceConfig = workspaceConfigurationResource;
|
||||
this.workspaceConfigWatcher = this.watchWorkspaceConfigurationFile();
|
||||
}
|
||||
return this.fileService.resolveContent(this.workspaceConfig).then(content => content.value);
|
||||
return this._workspaceIdentifier ? this.configurationFileService.watch(this._workspaceIdentifier.configPath) : Disposable.None;
|
||||
}
|
||||
|
||||
private handleWorkspaceFileEvents(event: FileChangesEvent): void {
|
||||
if (this.workspaceConfig) {
|
||||
if (this._workspaceIdentifier) {
|
||||
const events = event.changes;
|
||||
|
||||
let affectedByChanges = false;
|
||||
// Find changes that affect workspace file
|
||||
for (let i = 0, len = events.length; i < len && !affectedByChanges; i++) {
|
||||
affectedByChanges = resources.isEqual(this.workspaceConfig, events[i].resource);
|
||||
affectedByChanges = resources.isEqual(this._workspaceIdentifier.configPath, events[i].resource);
|
||||
}
|
||||
|
||||
if (affectedByChanges) {
|
||||
@@ -542,12 +428,6 @@ class FileServiceBasedWorkspaceConfiguration extends AbstractWorkspaceConfigurat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
|
||||
dispose(this.workspaceConfigWatcher);
|
||||
}
|
||||
}
|
||||
|
||||
class CachedWorkspaceConfiguration extends Disposable implements IWorkspaceConfiguration {
|
||||
@@ -617,45 +497,50 @@ class CachedWorkspaceConfiguration extends Disposable implements IWorkspaceConfi
|
||||
|
||||
export interface IFolderConfiguration extends IDisposable {
|
||||
readonly onDidChange: Event<void>;
|
||||
readonly loaded: boolean;
|
||||
loadConfiguration(): Promise<ConfigurationModel>;
|
||||
reprocess(): ConfigurationModel;
|
||||
}
|
||||
|
||||
export abstract class AbstractFolderConfiguration extends Disposable implements IFolderConfiguration {
|
||||
class FileServiceBasedFolderConfiguration extends Disposable implements IFolderConfiguration {
|
||||
|
||||
private _folderSettingsModelParser: FolderSettingsModelParser;
|
||||
private _standAloneConfigurations: ConfigurationModel[];
|
||||
private _cache: ConfigurationModel;
|
||||
private _loaded: boolean = false;
|
||||
|
||||
private readonly configurationNames: string[];
|
||||
protected readonly configurationResources: URI[];
|
||||
private changeEventTriggerScheduler: RunOnceScheduler;
|
||||
protected readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChange: Event<void> = this._onDidChange.event;
|
||||
|
||||
constructor(protected readonly configurationFolder: URI, workbenchState: WorkbenchState, from?: AbstractFolderConfiguration) {
|
||||
constructor(protected readonly configurationFolder: URI, workbenchState: WorkbenchState, private configurationFileService: IConfigurationFileService) {
|
||||
super();
|
||||
|
||||
this.configurationNames = [FOLDER_SETTINGS_NAME /*First one should be settings */, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY];
|
||||
this.configurationNames = [FOLDER_SETTINGS_NAME /*First one should be settings */, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY];
|
||||
this.configurationResources = this.configurationNames.map(name => resources.joinPath(this.configurationFolder, `${name}.json`));
|
||||
this._folderSettingsModelParser = from ? from._folderSettingsModelParser : new FolderSettingsModelParser(FOLDER_SETTINGS_PATH, WorkbenchState.WORKSPACE === workbenchState ? [ConfigurationScope.RESOURCE] : [ConfigurationScope.WINDOW, ConfigurationScope.RESOURCE]);
|
||||
this._standAloneConfigurations = from ? from._standAloneConfigurations : [];
|
||||
this._cache = from ? from._cache : new ConfigurationModel();
|
||||
}
|
||||
this._folderSettingsModelParser = new FolderSettingsModelParser(FOLDER_SETTINGS_PATH, WorkbenchState.WORKSPACE === workbenchState ? [ConfigurationScope.RESOURCE] : [ConfigurationScope.WINDOW, ConfigurationScope.RESOURCE]);
|
||||
this._standAloneConfigurations = [];
|
||||
this._cache = new ConfigurationModel();
|
||||
|
||||
get loaded(): boolean {
|
||||
return this._loaded;
|
||||
this.changeEventTriggerScheduler = this._register(new RunOnceScheduler(() => this._onDidChange.fire(), 50));
|
||||
this._register(configurationFileService.onFileChanges(e => this.handleWorkspaceFileEvents(e)));
|
||||
if (!this.configurationFileService.isWatching) {
|
||||
this.configurationFileService.whenWatchingStarted.then(() => this.onWatchStarted());
|
||||
}
|
||||
}
|
||||
|
||||
async loadConfiguration(): Promise<ConfigurationModel> {
|
||||
const configurationContents = await Promise.all(this.configurationResources.map(resource =>
|
||||
this.loadConfigurationResourceContents(resource)
|
||||
.then(undefined, error => {
|
||||
/* never fail */
|
||||
const configurationContents = await Promise.all(this.configurationResources.map(async resource => {
|
||||
try {
|
||||
return await this.configurationFileService.resolveContent(resource);
|
||||
} catch (error) {
|
||||
const exists = await this.configurationFileService.exists(resource);
|
||||
if (exists) {
|
||||
errors.onUnexpectedError(error);
|
||||
return undefined;
|
||||
})));
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}));
|
||||
|
||||
// reset
|
||||
this._standAloneConfigurations = [];
|
||||
@@ -677,7 +562,6 @@ export abstract class AbstractFolderConfiguration extends Disposable implements
|
||||
// Consolidate (support *.json files in the workspace settings folder)
|
||||
this.consolidate();
|
||||
|
||||
this._loaded = true;
|
||||
return this._cache;
|
||||
}
|
||||
|
||||
@@ -694,41 +578,13 @@ export abstract class AbstractFolderConfiguration extends Disposable implements
|
||||
this._cache = this._folderSettingsModelParser.configurationModel.merge(...this._standAloneConfigurations);
|
||||
}
|
||||
|
||||
protected abstract loadConfigurationResourceContents(configurationResource: URI): Promise<string | undefined>;
|
||||
}
|
||||
|
||||
export class NodeBasedFolderConfiguration extends AbstractFolderConfiguration {
|
||||
|
||||
constructor(private readonly configurationFileService: IConfigurationFileService, configurationFolder: URI, workbenchState: WorkbenchState) {
|
||||
super(configurationFolder, workbenchState);
|
||||
}
|
||||
|
||||
protected async loadConfigurationResourceContents(configurationResource: URI): Promise<string | undefined> {
|
||||
const exists = await this.configurationFileService.exists(configurationResource);
|
||||
if (exists) {
|
||||
return this.configurationFileService.resolveContent(configurationResource);
|
||||
private async onWatchStarted(): Promise<void> {
|
||||
const currentModel = this._cache;
|
||||
const newModel = await this.loadConfiguration();
|
||||
const { added, removed, updated } = compare(currentModel, newModel);
|
||||
if (added.length || removed.length || updated.length) {
|
||||
this._onDidChange.fire();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export class FileServiceBasedFolderConfiguration extends AbstractFolderConfiguration {
|
||||
|
||||
private changeEventTriggerScheduler: RunOnceScheduler;
|
||||
|
||||
constructor(configurationFolder: URI, workbenchState: WorkbenchState, private fileService: IFileService, from?: AbstractFolderConfiguration) {
|
||||
super(configurationFolder, workbenchState, from);
|
||||
this.changeEventTriggerScheduler = this._register(new RunOnceScheduler(() => this._onDidChange.fire(), 50));
|
||||
this._register(fileService.onFileChanges(e => this.handleWorkspaceFileEvents(e)));
|
||||
}
|
||||
|
||||
protected async loadConfigurationResourceContents(configurationResource: URI): Promise<string | undefined> {
|
||||
const exists = await this.fileService.exists(configurationResource);
|
||||
if (exists) {
|
||||
const contents = await this.fileService.resolveContent(configurationResource);
|
||||
return contents.value;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private handleWorkspaceFileEvents(event: FileChangesEvent): void {
|
||||
@@ -784,7 +640,6 @@ class CachedFolderConfiguration extends Disposable implements IFolderConfigurati
|
||||
|
||||
private configurationModel: ConfigurationModel;
|
||||
private readonly key: Thenable<ConfigurationKey>;
|
||||
loaded: boolean = false;
|
||||
|
||||
constructor(
|
||||
folder: URI,
|
||||
@@ -802,7 +657,6 @@ class CachedFolderConfiguration extends Disposable implements IFolderConfigurati
|
||||
const contents = await this.configurationCache.read(key);
|
||||
const parsed: IConfigurationModel = JSON.parse(contents.toString());
|
||||
this.configurationModel = new ConfigurationModel(parsed.contents, parsed.keys, parsed.overrides);
|
||||
this.loaded = true;
|
||||
} catch (e) {
|
||||
}
|
||||
return this.configurationModel;
|
||||
@@ -832,79 +686,44 @@ export class FolderConfiguration extends Disposable implements IFolderConfigurat
|
||||
readonly onDidChange: Event<void> = this._onDidChange.event;
|
||||
|
||||
private folderConfiguration: IFolderConfiguration;
|
||||
private folderConfigurationDisposable: IDisposable = Disposable.None;
|
||||
private readonly configurationFolder: URI;
|
||||
private cachedFolderConfiguration: CachedFolderConfiguration;
|
||||
private _loaded: boolean = false;
|
||||
|
||||
constructor(
|
||||
readonly workspaceFolder: IWorkspaceFolder,
|
||||
configFolderRelativePath: string,
|
||||
private readonly workbenchState: WorkbenchState,
|
||||
configurationFileService: IConfigurationFileService,
|
||||
configurationCache: IConfigurationCache,
|
||||
fileService?: IFileService
|
||||
configurationCache: IConfigurationCache
|
||||
) {
|
||||
super();
|
||||
|
||||
this.configurationFolder = resources.joinPath(workspaceFolder.uri, configFolderRelativePath);
|
||||
this.cachedFolderConfiguration = new CachedFolderConfiguration(workspaceFolder.uri, configFolderRelativePath, configurationCache);
|
||||
this.folderConfiguration = this.cachedFolderConfiguration;
|
||||
if (fileService) {
|
||||
this.folderConfiguration = new FileServiceBasedFolderConfiguration(this.configurationFolder, this.workbenchState, fileService);
|
||||
} else if (workspaceFolder.uri.scheme === Schemas.file) {
|
||||
this.folderConfiguration = new NodeBasedFolderConfiguration(configurationFileService, this.configurationFolder, this.workbenchState);
|
||||
this.folderConfiguration = this.cachedFolderConfiguration = new CachedFolderConfiguration(workspaceFolder.uri, configFolderRelativePath, configurationCache);
|
||||
if (workspaceFolder.uri.scheme === Schemas.file) {
|
||||
this.folderConfiguration = new FileServiceBasedFolderConfiguration(this.configurationFolder, this.workbenchState, configurationFileService);
|
||||
} else {
|
||||
configurationFileService.whenProviderRegistered(workspaceFolder.uri.scheme)
|
||||
.then(() => {
|
||||
this.folderConfiguration.dispose();
|
||||
this.folderConfigurationDisposable.dispose();
|
||||
this.folderConfiguration = new FileServiceBasedFolderConfiguration(this.configurationFolder, this.workbenchState, configurationFileService);
|
||||
this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange()));
|
||||
this.onDidFolderConfigurationChange();
|
||||
});
|
||||
}
|
||||
this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange()));
|
||||
this.folderConfigurationDisposable = this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange()));
|
||||
}
|
||||
|
||||
loadConfiguration(): Promise<ConfigurationModel> {
|
||||
return this.folderConfiguration.loadConfiguration()
|
||||
.then(model => {
|
||||
this._loaded = this.folderConfiguration.loaded;
|
||||
return model;
|
||||
});
|
||||
return this.folderConfiguration.loadConfiguration();
|
||||
}
|
||||
|
||||
reprocess(): ConfigurationModel {
|
||||
return this.folderConfiguration.reprocess();
|
||||
}
|
||||
|
||||
get loaded(): boolean {
|
||||
return this._loaded;
|
||||
}
|
||||
|
||||
adopt(fileService: IFileService): Promise<boolean> {
|
||||
if (fileService) {
|
||||
if (this.folderConfiguration instanceof CachedFolderConfiguration) {
|
||||
return this.adoptFromCachedConfiguration(fileService);
|
||||
}
|
||||
|
||||
if (this.folderConfiguration instanceof NodeBasedFolderConfiguration) {
|
||||
return this.adoptFromNodeBasedConfiguration(fileService);
|
||||
}
|
||||
}
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
private adoptFromCachedConfiguration(fileService: IFileService): Promise<boolean> {
|
||||
const folderConfiguration = new FileServiceBasedFolderConfiguration(this.configurationFolder, this.workbenchState, fileService);
|
||||
return folderConfiguration.loadConfiguration()
|
||||
.then(() => {
|
||||
this.folderConfiguration = folderConfiguration;
|
||||
this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange()));
|
||||
this.updateCache();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private adoptFromNodeBasedConfiguration(fileService: IFileService): Promise<boolean> {
|
||||
const oldFolderConfiguration = this.folderConfiguration;
|
||||
this.folderConfiguration = new FileServiceBasedFolderConfiguration(this.configurationFolder, this.workbenchState, fileService, <AbstractFolderConfiguration>oldFolderConfiguration);
|
||||
oldFolderConfiguration.dispose();
|
||||
this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange()));
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
private onDidFolderConfigurationChange(): void {
|
||||
this.updateCache();
|
||||
this._onDidChange.fire();
|
||||
|
||||
@@ -13,7 +13,6 @@ import { Queue, Barrier } from 'vs/base/common/async';
|
||||
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';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { ConfigurationChangeEvent, ConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
|
||||
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';
|
||||
@@ -23,13 +22,12 @@ import { IConfigurationRegistry, Extensions, allSettings, windowSettings, resour
|
||||
import { IWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, isSingleFolderWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, IEmptyWorkspaceInitializationPayload, useSlashForPath, getStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditingService';
|
||||
import { WorkspaceConfiguration, FolderConfiguration, RemoteUserConfiguration, LocalUserConfiguration } from 'vs/workbench/services/configuration/browser/configuration';
|
||||
import { WorkspaceConfiguration, FolderConfiguration, RemoteUserConfiguration, UserConfiguration } from 'vs/workbench/services/configuration/browser/configuration';
|
||||
import { JSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditingService';
|
||||
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';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
|
||||
export class WorkspaceService extends Disposable implements IConfigurationService, IWorkspaceContextService {
|
||||
@@ -41,7 +39,7 @@ export class WorkspaceService extends Disposable implements IConfigurationServic
|
||||
private readonly configurationCache: IConfigurationCache;
|
||||
private _configuration: Configuration;
|
||||
private defaultConfiguration: DefaultConfigurationModel;
|
||||
private localUserConfiguration: LocalUserConfiguration | null = null;
|
||||
private localUserConfiguration: UserConfiguration | null = null;
|
||||
private remoteUserConfiguration: RemoteUserConfiguration | null = null;
|
||||
private workspaceConfiguration: WorkspaceConfiguration;
|
||||
private cachedFolderConfigs: ResourceMap<FolderConfiguration>;
|
||||
@@ -60,14 +58,13 @@ export class WorkspaceService extends Disposable implements IConfigurationServic
|
||||
protected readonly _onDidChangeWorkbenchState: Emitter<WorkbenchState> = this._register(new Emitter<WorkbenchState>());
|
||||
public readonly onDidChangeWorkbenchState: Event<WorkbenchState> = this._onDidChangeWorkbenchState.event;
|
||||
|
||||
private fileService: IFileService;
|
||||
private configurationEditingService: ConfigurationEditingService;
|
||||
private jsonEditingService: JSONEditingService;
|
||||
|
||||
constructor(
|
||||
{ userSettingsResource, remoteAuthority, configurationCache }: { userSettingsResource?: URI, remoteAuthority?: string, configurationCache: IConfigurationCache },
|
||||
private readonly configurationFileService: IConfigurationFileService,
|
||||
private readonly remoteAgentService: IRemoteAgentService,
|
||||
remoteAgentService: IRemoteAgentService,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -75,11 +72,11 @@ export class WorkspaceService extends Disposable implements IConfigurationServic
|
||||
this.defaultConfiguration = new DefaultConfigurationModel();
|
||||
this.configurationCache = configurationCache;
|
||||
if (userSettingsResource) {
|
||||
this.localUserConfiguration = this._register(new LocalUserConfiguration(userSettingsResource, configurationFileService));
|
||||
this.localUserConfiguration = this._register(new UserConfiguration(userSettingsResource, configurationFileService));
|
||||
this._register(this.localUserConfiguration.onDidChangeConfiguration(userConfiguration => this.onLocalUserConfigurationChanged(userConfiguration)));
|
||||
}
|
||||
if (remoteAuthority) {
|
||||
this.remoteUserConfiguration = this._register(new RemoteUserConfiguration(remoteAuthority, configurationCache));
|
||||
this.remoteUserConfiguration = this._register(new RemoteUserConfiguration(remoteAuthority, configurationCache, configurationFileService, remoteAgentService));
|
||||
this._register(this.remoteUserConfiguration.onDidChangeConfiguration(userConfiguration => this.onRemoteUserConfigurationChanged(userConfiguration)));
|
||||
}
|
||||
this.workspaceConfiguration = this._register(new WorkspaceConfiguration(configurationCache, this.configurationFileService));
|
||||
@@ -229,9 +226,7 @@ export class WorkspaceService extends Disposable implements IConfigurationServic
|
||||
// Workspace Configuration Service Impl
|
||||
|
||||
getConfigurationData(): IConfigurationData {
|
||||
const configurationData = this._configuration.toData();
|
||||
configurationData.isComplete = this.cachedFolderConfigs.values().every(c => c.loaded);
|
||||
return configurationData;
|
||||
return this._configuration.toData();
|
||||
}
|
||||
|
||||
getValue<T>(): T;
|
||||
@@ -294,45 +289,6 @@ export class WorkspaceService extends Disposable implements IConfigurationServic
|
||||
});
|
||||
}
|
||||
|
||||
acquireFileService(fileService: IFileService): void {
|
||||
this.fileService = fileService;
|
||||
const changedWorkspaceFolders: IWorkspaceFolder[] = [];
|
||||
if (this.localUserConfiguration) {
|
||||
this.localUserConfiguration.adopt(fileService)
|
||||
.then(changedModel => {
|
||||
if (changedModel) {
|
||||
this.onLocalUserConfigurationChanged(changedModel);
|
||||
}
|
||||
});
|
||||
}
|
||||
Promise.all([this.workspaceConfiguration.adopt(fileService), ...this.cachedFolderConfigs.values()
|
||||
.map(folderConfiguration => folderConfiguration.adopt(fileService)
|
||||
.then(result => {
|
||||
if (result) {
|
||||
changedWorkspaceFolders.push(folderConfiguration.workspaceFolder);
|
||||
}
|
||||
return result;
|
||||
}))])
|
||||
.then(([workspaceChanged]) => {
|
||||
if (workspaceChanged) {
|
||||
this.onWorkspaceConfigurationChanged();
|
||||
}
|
||||
for (const workspaceFolder of changedWorkspaceFolders) {
|
||||
this.onWorkspaceFolderConfigurationChanged(workspaceFolder);
|
||||
}
|
||||
this.releaseWorkspaceBarrier();
|
||||
});
|
||||
if (this.remoteUserConfiguration) {
|
||||
this.remoteAgentService.getEnvironment()
|
||||
.then(environment => this.remoteUserConfiguration!.adopt(environment ? environment.appSettingsPath : null, fileService)
|
||||
.then(changedModel => {
|
||||
if (changedModel) {
|
||||
this.onRemoteUserConfigurationChanged(changedModel);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
acquireInstantiationService(instantiationService: IInstantiationService): void {
|
||||
this.configurationEditingService = instantiationService.createInstance(ConfigurationEditingService);
|
||||
this.jsonEditingService = instantiationService.createInstance(JSONEditingService);
|
||||
@@ -357,8 +313,8 @@ export class WorkspaceService extends Disposable implements IConfigurationServic
|
||||
const workspaceFolders = toWorkspaceFolders(this.workspaceConfiguration.getFolders(), dirname(workspaceConfigPath));
|
||||
const workspaceId = workspaceIdentifier.id;
|
||||
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.
|
||||
if (this.workspaceConfiguration.loaded) {
|
||||
this.releaseWorkspaceBarrier();
|
||||
}
|
||||
return workspace;
|
||||
});
|
||||
@@ -583,6 +539,9 @@ export class WorkspaceService extends Disposable implements IConfigurationServic
|
||||
this.triggerConfigurationChange(workspaceConfigurationChangeEvent, ConfigurationTarget.WORKSPACE);
|
||||
}
|
||||
}
|
||||
if (this.workspaceConfiguration.loaded) {
|
||||
this.releaseWorkspaceBarrier();
|
||||
}
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
@@ -629,7 +588,7 @@ export class WorkspaceService extends Disposable implements IConfigurationServic
|
||||
return Promise.all([...folders.map(folder => {
|
||||
let folderConfiguration = this.cachedFolderConfigs.get(folder.uri);
|
||||
if (!folderConfiguration) {
|
||||
folderConfiguration = new FolderConfiguration(folder, FOLDER_CONFIG_FOLDER_NAME, this.getWorkbenchState(), this.configurationFileService, this.configurationCache, this.fileService);
|
||||
folderConfiguration = new FolderConfiguration(folder, FOLDER_CONFIG_FOLDER_NAME, this.getWorkbenchState(), this.configurationFileService, this.configurationCache);
|
||||
this._register(folderConfiguration.onDidChange(() => this.onWorkspaceFolderConfigurationChanged(folder)));
|
||||
this.cachedFolderConfigs.set(folder.uri, this._register(folderConfiguration));
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { FileChangesEvent, IFileService } from 'vs/platform/files/common/files';
|
||||
|
||||
export const FOLDER_CONFIG_FOLDER_NAME = '.azuredatastudio';
|
||||
export const FOLDER_SETTINGS_NAME = 'settings';
|
||||
@@ -34,6 +37,48 @@ export interface IConfigurationCache {
|
||||
}
|
||||
|
||||
export interface IConfigurationFileService {
|
||||
fileService: IFileService | null;
|
||||
readonly onFileChanges: Event<FileChangesEvent>;
|
||||
readonly isWatching: boolean;
|
||||
readonly whenWatchingStarted: Promise<void>;
|
||||
whenProviderRegistered(scheme: string): Promise<void>;
|
||||
watch(resource: URI): IDisposable;
|
||||
exists(resource: URI): Promise<boolean>;
|
||||
resolveContent(resource: URI): Promise<string>;
|
||||
}
|
||||
|
||||
export class ConfigurationFileService implements IConfigurationFileService {
|
||||
|
||||
constructor(public fileService: IFileService) { }
|
||||
|
||||
get onFileChanges() { return this.fileService.onFileChanges; }
|
||||
readonly whenWatchingStarted: Promise<void> = Promise.resolve();
|
||||
readonly isWatching: boolean = true;
|
||||
|
||||
whenProviderRegistered(scheme: string): Promise<void> {
|
||||
if (this.fileService.canHandleResource(URI.from({ scheme }))) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise((c, e) => {
|
||||
const disposable = this.fileService.onDidChangeFileSystemProviderRegistrations(e => {
|
||||
if (e.scheme === scheme && e.added) {
|
||||
disposable.dispose();
|
||||
c();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
watch(resource: URI): IDisposable {
|
||||
return this.fileService.watch(resource);
|
||||
}
|
||||
|
||||
exists(resource: URI): Promise<boolean> {
|
||||
return this.fileService.exists(resource);
|
||||
}
|
||||
|
||||
resolveContent(resource: URI): Promise<string> {
|
||||
return this.fileService.resolveContent(resource, { encoding: 'utf8' }).then(content => content.value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,18 +4,76 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import { IConfigurationFileService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { IConfigurationFileService, ConfigurationFileService as FileServiceBasedConfigurationFileService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { FileChangesEvent, IFileService } from 'vs/platform/files/common/files';
|
||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
|
||||
export class ConfigurationFileService implements IConfigurationFileService {
|
||||
export class ConfigurationFileService extends Disposable implements IConfigurationFileService {
|
||||
|
||||
private _fileServiceBasedConfigurationFileService: FileServiceBasedConfigurationFileService | null = null;
|
||||
private _fileServiceBasedConfigurationFileServiceCallback: (fileServiceBasedConfigurationFileService: FileServiceBasedConfigurationFileService) => void;
|
||||
private _whenFileServiceBasedConfigurationFileServiceAvailable: Promise<FileServiceBasedConfigurationFileService> = new Promise((c) => this._fileServiceBasedConfigurationFileServiceCallback = c);
|
||||
private _watchResources: { resource: URI, disposable: { disposable: IDisposable | null } }[] = [];
|
||||
readonly whenWatchingStarted: Promise<void> = this._whenFileServiceBasedConfigurationFileServiceAvailable.then(() => undefined);
|
||||
|
||||
private readonly _onFileChanges: Emitter<FileChangesEvent> = this._register(new Emitter<FileChangesEvent>());
|
||||
readonly onFileChanges: Event<FileChangesEvent> = this._onFileChanges.event;
|
||||
|
||||
get isWatching(): boolean {
|
||||
return this._fileServiceBasedConfigurationFileService ? this._fileServiceBasedConfigurationFileService.isWatching : false;
|
||||
}
|
||||
|
||||
watch(resource: URI): IDisposable {
|
||||
if (this._fileServiceBasedConfigurationFileService) {
|
||||
return this._fileServiceBasedConfigurationFileService.watch(resource);
|
||||
}
|
||||
const disposable: { disposable: IDisposable | null } = { disposable: null };
|
||||
this._watchResources.push({ resource, disposable });
|
||||
return toDisposable(() => {
|
||||
if (disposable.disposable) {
|
||||
disposable.disposable.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
whenProviderRegistered(scheme: string): Promise<void> {
|
||||
if (scheme === Schemas.file) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return this._whenFileServiceBasedConfigurationFileServiceAvailable
|
||||
.then(fileServiceBasedConfigurationFileService => fileServiceBasedConfigurationFileService.whenProviderRegistered(scheme));
|
||||
}
|
||||
|
||||
exists(resource: URI): Promise<boolean> {
|
||||
return pfs.exists(resource.fsPath);
|
||||
return this._fileServiceBasedConfigurationFileService ? this._fileServiceBasedConfigurationFileService.exists(resource) : pfs.exists(resource.fsPath);
|
||||
}
|
||||
|
||||
async resolveContent(resource: URI): Promise<string> {
|
||||
const contents = await pfs.readFile(resource.fsPath);
|
||||
return contents.toString();
|
||||
if (this._fileServiceBasedConfigurationFileService) {
|
||||
return this._fileServiceBasedConfigurationFileService.resolveContent(resource);
|
||||
} else {
|
||||
const contents = await pfs.readFile(resource.fsPath);
|
||||
return contents.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private _fileService: IFileService | null;
|
||||
get fileService(): IFileService | null {
|
||||
return this._fileService;
|
||||
}
|
||||
|
||||
set fileService(fileService: IFileService | null) {
|
||||
if (fileService && !this._fileServiceBasedConfigurationFileService) {
|
||||
this._fileServiceBasedConfigurationFileService = new FileServiceBasedConfigurationFileService(fileService);
|
||||
this._fileService = fileService;
|
||||
this._register(this._fileServiceBasedConfigurationFileService.onFileChanges(e => this._onFileChanges.fire(e)));
|
||||
for (const { resource, disposable } of this._watchResources) {
|
||||
disposable.disposable = this._fileServiceBasedConfigurationFileService.watch(resource);
|
||||
}
|
||||
this._fileServiceBasedConfigurationFileServiceCallback(this._fileServiceBasedConfigurationFileService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user