diff --git a/src/vs/workbench/services/configuration/browser/configuration.ts b/src/vs/workbench/services/configuration/browser/configuration.ts index c3c02c415d86bffeb5f4d3baaebee31aa9e60aa8..b50b68adfb9a718448c80fd573a645250f689e3e 100644 --- a/src/vs/workbench/services/configuration/browser/configuration.ts +++ b/src/vs/workbench/services/configuration/browser/configuration.ts @@ -59,7 +59,7 @@ export class UserConfiguration extends Disposable { const fileServiceBasedConfiguration = new FileServiceBasedConfiguration(folder.toString(), [this.userSettingsResource], standAloneConfigurationResources, this.scopes, this.fileService); const configurationModel = await fileServiceBasedConfiguration.loadConfiguration(); this.userConfiguration.value = fileServiceBasedConfiguration; - this._register(this.userConfiguration.value.onDidChange(() => this.reloadConfigurationScheduler.schedule())); + this._register(fileServiceBasedConfiguration.onDidChange(() => this.reloadConfigurationScheduler.schedule())); return configurationModel; } @@ -108,7 +108,7 @@ class FileServiceBasedConfiguration extends Disposable { errors.onUnexpectedError(error); } } - return undefined; + return '{}'; })); }; @@ -723,6 +723,7 @@ export class FolderConfiguration extends Disposable implements IFolderConfigurat this.folderConfiguration = this.cachedFolderConfiguration = new CachedFolderConfiguration(workspaceFolder.uri, configFolderRelativePath, configurationCache); if (workspaceFolder.uri.scheme === Schemas.file) { this.folderConfiguration = this.createFileServiceBasedConfiguration(fileService); + this.folderConfigurationDisposable = this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange())); } else { whenProviderRegistered(workspaceFolder.uri, fileService) .then(() => { @@ -733,7 +734,6 @@ export class FolderConfiguration extends Disposable implements IFolderConfigurat this.onDidFolderConfigurationChange(); }); } - this.folderConfigurationDisposable = this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange())); } loadConfiguration(): Promise { diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 45de7c07ca163ba5313b64bd4de6cc815a0b5295..87c8c7d839a0b7586766a72501fcb12da4d3ab86 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -30,7 +30,7 @@ import { IJSONEditingService } from 'vs/workbench/services/configuration/common/ import { JSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditingService'; import { createHash } from 'crypto'; import { Schemas } from 'vs/base/common/network'; -import { originalFSPath } from 'vs/base/common/resources'; +import { originalFSPath, joinPath } from 'vs/base/common/resources'; import { isLinux } from 'vs/base/common/platform'; import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl'; import { RemoteAuthorityResolverService } from 'vs/platform/remote/electron-browser/remoteAuthorityResolverService'; @@ -47,6 +47,7 @@ import { IKeybindingEditingService, KeybindingsEditingService } from 'vs/workben import { NativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { timeout } from 'vs/base/common/async'; +import { VSBuffer } from 'vs/base/common/buffer'; class TestEnvironmentService extends NativeWorkbenchEnvironmentService { @@ -719,6 +720,7 @@ suite('WorkspaceConfigurationService - Folder', () => { let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceDir: string, testObject: IConfigurationService, globalSettingsFile: string, globalTasksFile: string, workspaceService: WorkspaceService; const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); + let fileService: IFileService; suiteSetup(() => { configurationRegistry.registerConfiguration({ @@ -767,7 +769,7 @@ suite('WorkspaceConfigurationService - Folder', () => { const environmentService = new TestEnvironmentService(URI.file(parentDir)); const remoteAgentService = instantiationService.createInstance(RemoteAgentService, {}); instantiationService.stub(IRemoteAgentService, remoteAgentService); - const fileService = new FileService(new NullLogService()); + fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); @@ -776,6 +778,9 @@ suite('WorkspaceConfigurationService - Folder', () => { instantiationService.stub(IConfigurationService, workspaceService); instantiationService.stub(IEnvironmentService, environmentService); + // Watch workspace configuration directory + fileService.watch(joinPath(URI.file(workspaceDir), '.vscode')); + return workspaceService.initialize(convertToWorkspacePayload(URI.file(folderDir))).then(() => { instantiationService.stub(IFileService, fileService); instantiationService.stub(IKeybindingEditingService, instantiationService.createInstance(KeybindingsEditingService)); @@ -1101,6 +1106,37 @@ suite('WorkspaceConfigurationService - Folder', () => { fs.writeFileSync(globalTasksFile, '{ "version": "1.0.0", "tasks": [{ "taskName": "myTask" }'); return new Promise((c) => testObject.onDidChangeConfiguration(() => c())); }); + + test('creating workspace settings', async () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); + await testObject.reloadConfiguration(); + const workspaceSettingsResource = URI.file(path.join(workspaceDir, '.vscode', 'settings.json')); + await new Promise(async (c) => { + const disposable = testObject.onDidChangeConfiguration(e => { + assert.ok(e.affectsConfiguration('configurationService.folder.testSetting')); + assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue'); + disposable.dispose(); + c(); + }); + await fileService.writeFile(workspaceSettingsResource, VSBuffer.fromString('{ "configurationService.folder.testSetting": "workspaceValue" }')); + }); + }); + + test('deleting workspace settings', async () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); + const workspaceSettingsResource = URI.file(path.join(workspaceDir, '.vscode', 'settings.json')); + await fileService.writeFile(workspaceSettingsResource, VSBuffer.fromString('{ "configurationService.folder.testSetting": "workspaceValue" }')); + await testObject.reloadConfiguration(); + await new Promise(async (c) => { + const disposable = testObject.onDidChangeConfiguration(e => { + assert.ok(e.affectsConfiguration('configurationService.folder.testSetting')); + assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'userValue'); + disposable.dispose(); + c(); + }); + await fileService.del(workspaceSettingsResource); + }); + }); }); suite('WorkspaceConfigurationService-Multiroot', () => {