Merge from vscode 1fbacccbc900bb59ba8a8f26a4128d48a1c97842

This commit is contained in:
ADS Merger
2020-02-13 02:56:02 +00:00
parent 9af1f3b0eb
commit 73ea8b79b2
229 changed files with 3192 additions and 2103 deletions

View File

@@ -13,6 +13,10 @@ import { OVERRIDE_PROPERTY_PATTERN, ConfigurationScope, IConfigurationRegistry,
import { IOverrides, overrideIdentifierFromKey, addToValueTree, toValuesTree, IConfigurationModel, getConfigurationValue, IConfigurationOverrides, IConfigurationData, getDefaultValues, getConfigurationKeys, removeFromValueTree, toOverrides, IConfigurationValue, ConfigurationTarget, compare, IConfigurationChangeEvent, IConfigurationChange } from 'vs/platform/configuration/common/configuration';
import { Workspace } from 'vs/platform/workspace/common/workspace';
import { Registry } from 'vs/platform/registry/common/platform';
import { Disposable } from 'vs/base/common/lifecycle';
import { Emitter, Event } from 'vs/base/common/event';
import { IFileService } from 'vs/platform/files/common/files';
import { dirname } from 'vs/base/common/resources';
export class ConfigurationModel implements IConfigurationModel {
@@ -335,6 +339,40 @@ export class ConfigurationModelParser {
}
}
export class UserSettings extends Disposable {
private readonly parser: ConfigurationModelParser;
protected readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
readonly onDidChange: Event<void> = this._onDidChange.event;
constructor(
private readonly userSettingsResource: URI,
private readonly scopes: ConfigurationScope[] | undefined,
private readonly fileService: IFileService
) {
super();
this.parser = new ConfigurationModelParser(this.userSettingsResource.toString(), this.scopes);
this._register(this.fileService.watch(dirname(this.userSettingsResource)));
this._register(Event.filter(this.fileService.onFileChanges, e => e.contains(this.userSettingsResource))(() => this._onDidChange.fire()));
}
async loadConfiguration(): Promise<ConfigurationModel> {
try {
const content = await this.fileService.readFile(this.userSettingsResource);
this.parser.parseContent(content.value.toString() || '{}');
return this.parser.configurationModel;
} catch (e) {
return new ConfigurationModel();
}
}
reprocess(): ConfigurationModel {
this.parser.parse();
return this.parser.configurationModel;
}
}
export class Configuration {
private _workspaceConsolidatedConfiguration: ConfigurationModel | null = null;

View File

@@ -7,54 +7,39 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides, ConfigurationTarget, isConfigurationOverrides, IConfigurationData, IConfigurationValue, IConfigurationChange } from 'vs/platform/configuration/common/configuration';
import { DefaultConfigurationModel, Configuration, ConfigurationModel, ConfigurationModelParser, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels';
import { DefaultConfigurationModel, Configuration, ConfigurationModel, ConfigurationChangeEvent, UserSettings } from 'vs/platform/configuration/common/configurationModels';
import { Event, Emitter } from 'vs/base/common/event';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { ConfigWatcher } from 'vs/base/node/config';
import { onUnexpectedError } from 'vs/base/common/errors';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { IFileService } from 'vs/platform/files/common/files';
import { RunOnceScheduler } from 'vs/base/common/async';
export class ConfigurationService extends Disposable implements IConfigurationService, IDisposable {
_serviceBrand: undefined;
private configuration: Configuration;
private userConfigModelWatcher: ConfigWatcher<ConfigurationModelParser> | undefined;
private userConfiguration: UserSettings;
private readonly reloadConfigurationScheduler: RunOnceScheduler;
private readonly _onDidChangeConfiguration: Emitter<IConfigurationChangeEvent> = this._register(new Emitter<IConfigurationChangeEvent>());
readonly onDidChangeConfiguration: Event<IConfigurationChangeEvent> = this._onDidChangeConfiguration.event;
constructor(
private readonly settingsResource: URI
private readonly settingsResource: URI,
fileService: IFileService
) {
super();
this.userConfiguration = this._register(new UserSettings(this.settingsResource, undefined, fileService));
this.configuration = new Configuration(new DefaultConfigurationModel(), new ConfigurationModel());
this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.reloadConfiguration(), 50));
this._register(Registry.as<IConfigurationRegistry>(Extensions.Configuration).onDidUpdateConfiguration(configurationProperties => this.onDidDefaultConfigurationChange(configurationProperties)));
this._register(this.userConfiguration.onDidChange(() => this.reloadConfigurationScheduler.schedule()));
}
initialize(): Promise<void> {
if (this.userConfigModelWatcher) {
this.userConfigModelWatcher.dispose();
}
if (this.settingsResource.scheme !== Schemas.file) {
return Promise.resolve();
}
return new Promise<void>((c, e) => {
this.userConfigModelWatcher = this._register(new ConfigWatcher(this.settingsResource.fsPath, {
changeBufferDelay: 300, onError: error => onUnexpectedError(error), defaultConfig: new ConfigurationModelParser(this.settingsResource.fsPath), parse: (content: string, parseErrors: any[]) => {
const userConfigModelParser = new ConfigurationModelParser(this.settingsResource.fsPath);
userConfigModelParser.parseContent(content);
parseErrors = [...userConfigModelParser.errors];
return userConfigModelParser;
}, initCallback: () => {
this.configuration = new Configuration(new DefaultConfigurationModel(), this.userConfigModelWatcher!.getConfig().configurationModel);
this._register(this.userConfigModelWatcher!.onDidUpdateConfiguration(() => this.onDidChangeUserConfiguration(this.userConfigModelWatcher!.getConfig().configurationModel)));
c();
}
}));
});
async initialize(): Promise<void> {
const userConfiguration = await this.userConfiguration.loadConfiguration();
this.configuration = new Configuration(new DefaultConfigurationModel(), userConfiguration);
}
getConfigurationData(): IConfigurationData {
@@ -92,14 +77,9 @@ export class ConfigurationService extends Disposable implements IConfigurationSe
return this.configuration.keys(undefined);
}
reloadConfiguration(folder?: IWorkspaceFolder): Promise<void> {
if (this.userConfigModelWatcher) {
return new Promise<void>(c => this.userConfigModelWatcher!.reload(userConfigModelParser => {
this.onDidChangeUserConfiguration(userConfigModelParser.configurationModel);
c();
}));
}
return this.initialize();
async reloadConfiguration(): Promise<void> {
const configurationModel = await this.userConfiguration.loadConfiguration();
this.onDidChangeUserConfiguration(configurationModel);
}
private onDidChangeUserConfiguration(userConfigurationModel: ConfigurationModel): void {

View File

@@ -16,14 +16,32 @@ import { testFile } from 'vs/base/test/node/utils';
import { URI } from 'vs/base/common/uri';
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { Event } from 'vs/base/common/event';
import { NullLogService } from 'vs/platform/log/common/log';
import { FileService } from 'vs/platform/files/common/fileService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
import { Schemas } from 'vs/base/common/network';
import { IFileService } from 'vs/platform/files/common/files';
suite('ConfigurationService - Node', () => {
let fileService: IFileService;
const disposables: IDisposable[] = [];
setup(() => {
const logService = new NullLogService();
fileService = new FileService(logService);
disposables.push(fileService);
const diskFileSystemProvider = new DiskFileSystemProvider(logService);
disposables.push(diskFileSystemProvider);
fileService.registerProvider(Schemas.file, diskFileSystemProvider);
});
test('simple', async () => {
const res = await testFile('config', 'config.json');
fs.writeFileSync(res.testFile, '{ "foo": "bar" }');
const service = new ConfigurationService(URI.file(res.testFile));
const service = new ConfigurationService(URI.file(res.testFile), fileService);
await service.initialize();
const config = service.getValue<{
foo: string;
@@ -41,7 +59,7 @@ suite('ConfigurationService - Node', () => {
fs.writeFileSync(res.testFile, '{ "testworkbench.editor.tabs": true }');
const service = new ConfigurationService(URI.file(res.testFile));
const service = new ConfigurationService(URI.file(res.testFile), fileService);
await service.initialize();
const config = service.getValue<{
testworkbench: {
@@ -64,7 +82,7 @@ suite('ConfigurationService - Node', () => {
fs.writeFileSync(res.testFile, ',,,,');
const service = new ConfigurationService(URI.file(res.testFile));
const service = new ConfigurationService(URI.file(res.testFile), fileService);
await service.initialize();
const config = service.getValue<{
foo: string;
@@ -81,7 +99,7 @@ suite('ConfigurationService - Node', () => {
const newDir = path.join(parentDir, 'config', id);
const testFile = path.join(newDir, 'config.json');
const service = new ConfigurationService(URI.file(testFile));
const service = new ConfigurationService(URI.file(testFile), fileService);
await service.initialize();
const config = service.getValue<{ foo: string }>();
@@ -90,10 +108,10 @@ suite('ConfigurationService - Node', () => {
service.dispose();
});
test('trigger configuration change event', async () => {
test('trigger configuration change event when file does not exist', async () => {
const res = await testFile('config', 'config.json');
const service = new ConfigurationService(URI.file(res.testFile));
const service = new ConfigurationService(URI.file(res.testFile), fileService);
await service.initialize();
return new Promise((c, e) => {
const disposable = Event.filter(service.onDidChangeConfiguration, e => e.source === ConfigurationTarget.USER)(async (e) => {
@@ -108,12 +126,31 @@ suite('ConfigurationService - Node', () => {
});
test('trigger configuration change event when file exists', async () => {
const res = await testFile('config', 'config.json');
const service = new ConfigurationService(URI.file(res.testFile), fileService);
fs.writeFileSync(res.testFile, '{ "foo": "bar" }');
await service.initialize();
return new Promise((c, e) => {
const disposable = Event.filter(service.onDidChangeConfiguration, e => e.source === ConfigurationTarget.USER)(async (e) => {
disposable.dispose();
assert.equal(service.getValue('foo'), 'barz');
service.dispose();
await res.cleanUp();
c();
});
fs.writeFileSync(res.testFile, '{ "foo": "barz" }');
});
});
test('reloadConfiguration', async () => {
const res = await testFile('config', 'config.json');
fs.writeFileSync(res.testFile, '{ "foo": "bar" }');
const service = new ConfigurationService(URI.file(res.testFile));
const service = new ConfigurationService(URI.file(res.testFile), fileService);
await service.initialize();
let config = service.getValue<{
foo: string;
@@ -162,7 +199,7 @@ suite('ConfigurationService - Node', () => {
}
});
let serviceWithoutFile = new ConfigurationService(URI.file('__testFile'));
let serviceWithoutFile = new ConfigurationService(URI.file('__testFile'), fileService);
await serviceWithoutFile.initialize();
let setting = serviceWithoutFile.getValue<ITestSetting>();
@@ -172,7 +209,7 @@ suite('ConfigurationService - Node', () => {
return testFile('config', 'config.json').then(async res => {
fs.writeFileSync(res.testFile, '{ "testworkbench.editor.tabs": true }');
const service = new ConfigurationService(URI.file(res.testFile));
const service = new ConfigurationService(URI.file(res.testFile), fileService);
let setting = service.getValue<ITestSetting>();
@@ -205,7 +242,7 @@ suite('ConfigurationService - Node', () => {
});
const r = await testFile('config', 'config.json');
const service = new ConfigurationService(URI.file(r.testFile));
const service = new ConfigurationService(URI.file(r.testFile), fileService);
service.initialize();
let res = service.inspect('something.missing');
@@ -243,7 +280,7 @@ suite('ConfigurationService - Node', () => {
});
const r = await testFile('config', 'config.json');
const service = new ConfigurationService(URI.file(r.testFile));
const service = new ConfigurationService(URI.file(r.testFile), fileService);
service.initialize();
let res = service.inspect('lookup.service.testNullSetting');