support debug & tasks writing (for #8937)
This commit is contained in:
parent
a4a100213d
commit
91115aa714
|
@ -33,6 +33,6 @@ export class MainThreadConfiguration extends MainThreadConfigurationShape {
|
|||
}
|
||||
|
||||
$updateConfigurationOption(target: ConfigurationTarget, key: string, value: any): TPromise<void> {
|
||||
return this._configurationEditingService.writeConfiguration(target, [{ key, value }]);
|
||||
return this._configurationEditingService.writeConfiguration(target, { key, value });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,11 @@ export enum ConfigurationEditingErrorCode {
|
|||
*/
|
||||
ERROR_UNKNOWN_KEY,
|
||||
|
||||
/**
|
||||
* Error when trying to write to user target but not supported for provided key.
|
||||
*/
|
||||
ERROR_INVALID_TARGET,
|
||||
|
||||
/**
|
||||
* Error when trying to write to the workspace configuration without having a workspace opened.
|
||||
*/
|
||||
|
@ -63,5 +68,5 @@ export interface IConfigurationEditingService {
|
|||
* Allows to write to either the user or workspace configuration file. The returned promise will be
|
||||
* in error state in any of the error cases from [ConfigurationEditingErrorCode](#ConfigurationEditingErrorCode)
|
||||
*/
|
||||
writeConfiguration(target: ConfigurationTarget, values: IConfigurationValue[]): TPromise<void>;
|
||||
writeConfiguration(target: ConfigurationTarget, value: IConfigurationValue): TPromise<void>;
|
||||
}
|
|
@ -21,6 +21,16 @@ import {IConfigurationService} from 'vs/platform/configuration/common/configurat
|
|||
import {WORKSPACE_CONFIG_DEFAULT_PATH} from 'vs/workbench/services/configuration/common/configuration';
|
||||
import {IConfigurationEditingService, ConfigurationEditingErrorCode, IConfigurationEditingError, ConfigurationTarget, IConfigurationValue} from 'vs/workbench/services/configuration/common/configurationEditing';
|
||||
|
||||
export const WORKSPACE_STANDALONE_CONFIGURATIONS = {
|
||||
'tasks': '.vscode/tasks.json',
|
||||
'launch': '.vscode/launch.json'
|
||||
};
|
||||
|
||||
interface IConfigurationEditOperation extends IConfigurationValue {
|
||||
target: URI;
|
||||
isWorkspaceStandalone?: boolean;
|
||||
}
|
||||
|
||||
interface IValidationResult {
|
||||
error?: ConfigurationEditingErrorCode;
|
||||
exists?: boolean;
|
||||
|
@ -39,16 +49,17 @@ export class ConfigurationEditingService implements IConfigurationEditingService
|
|||
) {
|
||||
}
|
||||
|
||||
public writeConfiguration(target: ConfigurationTarget, values: IConfigurationValue[]): TPromise<void> {
|
||||
public writeConfiguration(target: ConfigurationTarget, value: IConfigurationValue): TPromise<void> {
|
||||
const operation = this.getConfigurationEditOperation(target, value);
|
||||
|
||||
// First validate before making any edits
|
||||
return this.validate(target, values).then(validation => {
|
||||
return this.validate(target, operation).then(validation => {
|
||||
if (typeof validation.error === 'number') {
|
||||
return this.wrapError(validation.error);
|
||||
}
|
||||
|
||||
// Create configuration file if missing
|
||||
const resource = this.getConfigurationResource(target);
|
||||
const resource = operation.target;
|
||||
let ensureConfigurationFile = TPromise.as(null);
|
||||
let contents: string;
|
||||
if (!validation.exists) {
|
||||
|
@ -61,7 +72,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService
|
|||
return ensureConfigurationFile.then(() => {
|
||||
|
||||
// Apply all edits to the configuration file
|
||||
const result = this.applyEdits(contents, values);
|
||||
const result = this.applyEdits(contents, [operation]);
|
||||
|
||||
return pfs.writeFile(resource.fsPath, result, encoding.UTF8).then(() => {
|
||||
|
||||
|
@ -85,6 +96,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService
|
|||
private toErrorMessage(error: ConfigurationEditingErrorCode): string {
|
||||
switch (error) {
|
||||
case ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY: return nls.localize('errorUnknownKey', "Unable to write to the configuration file (Unknown Key)");
|
||||
case ConfigurationEditingErrorCode.ERROR_INVALID_TARGET: return nls.localize('errorInvalidTarget', "Unable to write to the configuration file (Invalid Target)");
|
||||
case ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED: return nls.localize('errorWorkspaceOpened', "Unable to write to the configuration file (No Workspace Opened)");
|
||||
case ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION: return nls.localize('errorInvalidConfiguration', "Unable to write to the configuration file (Invalid Configuration Found)");
|
||||
case ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY: return nls.localize('errorConfigurationFileDirty', "Unable to write to the configuration file (Configuration File Dirty)");
|
||||
|
@ -105,27 +117,34 @@ export class ConfigurationEditingService implements IConfigurationEditingService
|
|||
return content;
|
||||
}
|
||||
|
||||
private validate(target: ConfigurationTarget, values: IConfigurationValue[]): TPromise<IValidationResult> {
|
||||
private validate(target: ConfigurationTarget, operation: IConfigurationEditOperation): TPromise<IValidationResult> {
|
||||
|
||||
// 1.) Any key must be a known setting from the registry
|
||||
const validKeys = getConfigurationKeys();
|
||||
if (values.some(v => validKeys.indexOf(v.key) < 0)) {
|
||||
return TPromise.as({ error: ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY });
|
||||
// Any key must be a known setting from the registry (unless this is a standalone config)
|
||||
if (!operation.isWorkspaceStandalone) {
|
||||
const validKeys = getConfigurationKeys();
|
||||
if (validKeys.indexOf(operation.key) < 0) {
|
||||
return TPromise.as({ error: ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY });
|
||||
}
|
||||
}
|
||||
|
||||
// 2.) Target cannot be workspace if no workspace opened
|
||||
// Target cannot be user if is standalone
|
||||
if (operation.isWorkspaceStandalone && target === ConfigurationTarget.USER) {
|
||||
return TPromise.as({ error: ConfigurationEditingErrorCode.ERROR_INVALID_TARGET });
|
||||
}
|
||||
|
||||
// Target cannot be workspace if no workspace opened
|
||||
if (target === ConfigurationTarget.WORKSPACE && !this.contextService.getWorkspace()) {
|
||||
return TPromise.as({ error: ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED });
|
||||
}
|
||||
|
||||
// 3.) Target cannot be dirty
|
||||
const resource = this.getConfigurationResource(target);
|
||||
// Target cannot be dirty
|
||||
const resource = operation.target;
|
||||
return this.editorService.createInput({ resource }).then(typedInput => {
|
||||
if (typedInput.isDirty()) {
|
||||
return { error: ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY };
|
||||
}
|
||||
|
||||
// 4.) Target cannot contain JSON errors
|
||||
// Target cannot contain JSON errors
|
||||
return pfs.exists(resource.fsPath).then(exists => {
|
||||
if (!exists) {
|
||||
return { exists };
|
||||
|
@ -146,11 +165,26 @@ export class ConfigurationEditingService implements IConfigurationEditingService
|
|||
});
|
||||
}
|
||||
|
||||
private getConfigurationResource(target: ConfigurationTarget): URI {
|
||||
if (target === ConfigurationTarget.USER) {
|
||||
return URI.file(this.environmentService.appSettingsPath);
|
||||
private getConfigurationEditOperation(target: ConfigurationTarget, config: IConfigurationValue): IConfigurationEditOperation {
|
||||
|
||||
// Check for standalone workspace configurations
|
||||
if (config.key) {
|
||||
const standaloneConfigurationKeys = Object.keys(WORKSPACE_STANDALONE_CONFIGURATIONS);
|
||||
for (let i = 0; i < standaloneConfigurationKeys.length; i++) {
|
||||
const key = standaloneConfigurationKeys[i];
|
||||
const keyPrefix = `${key}.`;
|
||||
const target = this.contextService.toResource(WORKSPACE_STANDALONE_CONFIGURATIONS[key]);
|
||||
|
||||
if (config.key.indexOf(keyPrefix) === 0) {
|
||||
return { key: config.key.substr(keyPrefix.length), value: config.value, target, isWorkspaceStandalone: true };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.contextService.toResource(WORKSPACE_CONFIG_DEFAULT_PATH);
|
||||
if (target === ConfigurationTarget.USER) {
|
||||
return { key: config.key, value: config.value, target: URI.file(this.environmentService.appSettingsPath) };
|
||||
}
|
||||
|
||||
return { key: config.key, value: config.value, target: this.contextService.toResource(WORKSPACE_CONFIG_DEFAULT_PATH) };
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ import uuid = require('vs/base/common/uuid');
|
|||
import {IConfigurationRegistry, Extensions as ConfigurationExtensions} from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import {WorkspaceConfigurationService} from 'vs/workbench/services/configuration/node/configurationService';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import {ConfigurationEditingService} from 'vs/workbench/services/configuration/node/configurationEditingService';
|
||||
import {ConfigurationEditingService, WORKSPACE_STANDALONE_CONFIGURATIONS} from 'vs/workbench/services/configuration/node/configurationEditingService';
|
||||
import {ConfigurationTarget, IConfigurationEditingError, ConfigurationEditingErrorCode} from 'vs/workbench/services/configuration/common/configurationEditing';
|
||||
import {IResourceInput} from 'vs/platform/editor/common/editor';
|
||||
|
||||
|
@ -111,7 +111,7 @@ suite('WorkspaceConfigurationEditingService - Node', () => {
|
|||
test('errors cases - invalid key', (done: () => void) => {
|
||||
createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => {
|
||||
return createServices(workspaceDir, globalSettingsFile, false, true /* no workspace */).then(services => {
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, [{ key: 'unknown.key', value: 'value' }]).then(res => {
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'unknown.key', value: 'value' }).then(res => {
|
||||
}, (error:IConfigurationEditingError) => {
|
||||
assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY);
|
||||
services.configurationService.dispose();
|
||||
|
@ -121,10 +121,23 @@ suite('WorkspaceConfigurationEditingService - Node', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('errors cases - invalid target', (done: () => void) => {
|
||||
createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => {
|
||||
return createServices(workspaceDir, globalSettingsFile).then(services => {
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'tasks.something', value: 'value' }).then(res => {
|
||||
}, (error:IConfigurationEditingError) => {
|
||||
assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_TARGET);
|
||||
services.configurationService.dispose();
|
||||
cleanUp(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('errors cases - no workspace', (done: () => void) => {
|
||||
createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => {
|
||||
return createServices(workspaceDir, globalSettingsFile, false, true /* no workspace */).then(services => {
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, [{ key: 'configurationEditing.service.testSetting', value: 'value' }]).then(res => {
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'configurationEditing.service.testSetting', value: 'value' }).then(res => {
|
||||
}, (error: IConfigurationEditingError) => {
|
||||
assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED);
|
||||
services.configurationService.dispose();
|
||||
|
@ -139,7 +152,7 @@ suite('WorkspaceConfigurationEditingService - Node', () => {
|
|||
return createServices(workspaceDir, globalSettingsFile).then(services => {
|
||||
fs.writeFileSync(globalSettingsFile, ',,,,,,,,,,,,,,');
|
||||
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, [{ key: 'configurationEditing.service.testSetting', value: 'value' }]).then(res => {
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }).then(res => {
|
||||
}, (error: IConfigurationEditingError) => {
|
||||
assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION);
|
||||
services.configurationService.dispose();
|
||||
|
@ -152,7 +165,7 @@ suite('WorkspaceConfigurationEditingService - Node', () => {
|
|||
test('errors cases - dirty', (done: () => void) => {
|
||||
createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => {
|
||||
return createServices(workspaceDir, globalSettingsFile, true).then(services => {
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, [{ key: 'configurationEditing.service.testSetting', value: 'value' }]).then(res => {
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }).then(res => {
|
||||
}, (error: IConfigurationEditingError) => {
|
||||
assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY);
|
||||
services.configurationService.dispose();
|
||||
|
@ -165,7 +178,7 @@ suite('WorkspaceConfigurationEditingService - Node', () => {
|
|||
test('write one setting - empty file', (done: () => void) => {
|
||||
createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => {
|
||||
return createServices(workspaceDir, globalSettingsFile).then(services => {
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, [{ key: 'configurationEditing.service.testSetting', value: 'value' }]).then(res => {
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }).then(res => {
|
||||
const contents = fs.readFileSync(globalSettingsFile).toString('utf8');
|
||||
const parsed = json.parse(contents);
|
||||
assert.equal(parsed['configurationEditing.service.testSetting'], 'value');
|
||||
|
@ -183,7 +196,7 @@ suite('WorkspaceConfigurationEditingService - Node', () => {
|
|||
return createServices(workspaceDir, globalSettingsFile).then(services => {
|
||||
fs.writeFileSync(globalSettingsFile, '{ "my.super.setting": "my.super.value" }');
|
||||
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, [{ key: 'configurationEditing.service.testSetting', value: 'value' }]).then(res => {
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }).then(res => {
|
||||
const contents = fs.readFileSync(globalSettingsFile).toString('utf8');
|
||||
const parsed = json.parse(contents);
|
||||
assert.equal(parsed['configurationEditing.service.testSetting'], 'value');
|
||||
|
@ -199,22 +212,15 @@ suite('WorkspaceConfigurationEditingService - Node', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('write multiple settings - empty file', (done: () => void) => {
|
||||
test('write workspace standalone setting - empty file', (done: () => void) => {
|
||||
createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => {
|
||||
return createServices(workspaceDir, globalSettingsFile).then(services => {
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, [
|
||||
{ key: 'configurationEditing.service.testSetting', value: 'value' },
|
||||
{ key: 'configurationEditing.service.testSettingTwo', value: { complex: { value: true } } },
|
||||
{ key: 'configurationEditing.service.testSettingThree', value: 55 }
|
||||
]).then(res => {
|
||||
const contents = fs.readFileSync(globalSettingsFile).toString('utf8');
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks.service.testSetting', value: 'value' }).then(res => {
|
||||
const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
|
||||
const contents = fs.readFileSync(target).toString('utf8');
|
||||
const parsed = json.parse(contents);
|
||||
assert.equal(parsed['configurationEditing.service.testSetting'], 'value');
|
||||
assert.equal(parsed['configurationEditing.service.testSettingTwo'].complex.value, true);
|
||||
assert.equal(parsed['configurationEditing.service.testSettingThree'], 55);
|
||||
|
||||
assert.equal(services.configurationService.lookup('configurationEditing.service.testSetting').value, 'value');
|
||||
assert.equal(services.configurationService.lookup('configurationEditing.service.testSettingThree').value, 55);
|
||||
assert.equal(parsed['service.testSetting'], 'value');
|
||||
assert.equal(services.configurationService.lookup('tasks.service.testSetting').value, 'value');
|
||||
|
||||
services.configurationService.dispose();
|
||||
cleanUp(done);
|
||||
|
@ -223,27 +229,21 @@ suite('WorkspaceConfigurationEditingService - Node', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('write multiple settings - existing file', (done: () => void) => {
|
||||
test('write workspace standalone setting - existing file', (done: () => void) => {
|
||||
createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => {
|
||||
return createServices(workspaceDir, globalSettingsFile).then(services => {
|
||||
fs.writeFileSync(globalSettingsFile, '// some comment from me\n{ "my.super.setting": "my.super.value" }\n\n// more comments');
|
||||
const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['launch']);
|
||||
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, [
|
||||
{ key: 'configurationEditing.service.testSetting', value: 'value' },
|
||||
{ key: 'configurationEditing.service.testSettingTwo', value: { complex: { value: true } } },
|
||||
{ key: 'configurationEditing.service.testSettingThree', value: 55 }
|
||||
]).then(res => {
|
||||
const contents = fs.readFileSync(globalSettingsFile).toString('utf8');
|
||||
fs.writeFileSync(target, '{ "my.super.setting": "my.super.value" }');
|
||||
|
||||
return services.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'launch.service.testSetting', value: 'value' }).then(res => {
|
||||
const contents = fs.readFileSync(target).toString('utf8');
|
||||
const parsed = json.parse(contents);
|
||||
assert.equal(parsed['configurationEditing.service.testSetting'], 'value');
|
||||
assert.equal(parsed['configurationEditing.service.testSettingTwo'].complex.value, true);
|
||||
assert.equal(parsed['configurationEditing.service.testSettingThree'], 55);
|
||||
|
||||
assert.equal(parsed['service.testSetting'], 'value');
|
||||
assert.equal(parsed['my.super.setting'], 'my.super.value');
|
||||
|
||||
assert.equal(services.configurationService.lookup('my.super.setting').value, 'my.super.value');
|
||||
assert.equal(services.configurationService.lookup('configurationEditing.service.testSetting').value, 'value');
|
||||
assert.equal(services.configurationService.lookup('configurationEditing.service.testSettingThree').value, 55);
|
||||
assert.equal(services.configurationService.lookup('launch.service.testSetting').value, 'value');
|
||||
assert.equal(services.configurationService.lookup('launch.my.super.setting').value, 'my.super.value');
|
||||
|
||||
services.configurationService.dispose();
|
||||
cleanUp(done);
|
||||
|
|
Loading…
Reference in a new issue