diff --git a/src/vs/base/common/json.ts b/src/vs/base/common/json.ts index 1a4c6873d89..48b69f1ca13 100644 --- a/src/vs/base/common/json.ts +++ b/src/vs/base/common/json.ts @@ -817,6 +817,7 @@ export function getLocation(text: string, position: number): Location { export interface ParseOptions { disallowComments?: boolean; + allowTrailingComma?: boolean; } /** @@ -1005,6 +1006,7 @@ export function visit(text: string, visitor: JSONVisitor, options?: ParseOptions onError = toOneArgVisit(visitor.onError); let disallowComments = options && options.disallowComments; + let allowTrailingComma = options && options.allowTrailingComma; function scanNext(): SyntaxKind { while (true) { let token = _scanner.scan(); @@ -1116,6 +1118,9 @@ export function visit(text: string, visitor: JSONVisitor, options?: ParseOptions } onSeparator(','); scanNext(); // consume comma + if (_scanner.getToken() === SyntaxKind.CloseBraceToken && allowTrailingComma) { + break; + } } else if (needsComma) { handleError(ParseErrorCode.CommaExpected, [], []); } diff --git a/src/vs/base/test/common/json.test.ts b/src/vs/base/test/common/json.test.ts index 5a92584c1f7..dbea524ee58 100644 --- a/src/vs/base/test/common/json.test.ts +++ b/src/vs/base/test/common/json.test.ts @@ -234,6 +234,17 @@ suite('JSON', () => { assertInvalidParse('{ "foo": /*comment*/ true }', { foo: true }, options); }); + test('parse: trailing comma', () => { + let options = { allowTrailingComma: true }; + assertValidParse('{ "hello": [], }', { hello: [] }, options); + assertValidParse('{ "hello": [] }', { hello: [] }, options); + assertValidParse('{ "hello": [], "world": {}, }', { hello: [], world: {} }, options); + assertValidParse('{ "hello": [], "world": {} }', { hello: [], world: {} }, options); + + assertInvalidParse('{ "hello": [], }', { hello: [] }); + assertInvalidParse('{ "hello": [], "world": {}, }', { hello: [], world: {} }); + }); + test('location: properties', () => { assertLocation('|{ "foo": "bar" }', [], void 0, false); assertLocation('{| "foo": "bar" }', [], void 0, true); diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index 903af009327..d68c803db5c 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -233,7 +233,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService let error = void 0; const parseErrors: json.ParseError[] = []; - json.parse(content, parseErrors); + json.parse(content, parseErrors, { allowTrailingComma: true }); if (!options.writeToBuffer && parseErrors.length > 0) { error = ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION; }