diff --git a/src/vs/base/common/json.ts b/src/vs/base/common/json.ts index f8f7a40075b79825712b952b0159cafca0a0e073..1a4c6873d89832122bf75eea433b162919d9ad81 100644 --- a/src/vs/base/common/json.ts +++ b/src/vs/base/common/json.ts @@ -885,7 +885,6 @@ export function parseTree(text: string, errors: ParseError[] = [], options?: Par function onValue(valueNode: Node): Node { currentParent.children.push(valueNode); - ensurePropertyComplete(valueNode.offset + valueNode.length); return valueNode; } @@ -898,9 +897,9 @@ export function parseTree(text: string, errors: ParseError[] = [], options?: Par currentParent.children.push({ type: 'string', value: name, offset, length, parent: currentParent }); }, onObjectEnd: (offset: number, length: number) => { - ensurePropertyComplete(offset); currentParent.length = offset + length - currentParent.offset; currentParent = currentParent.parent; + ensurePropertyComplete(offset + length); }, onArrayBegin: (offset: number, length: number) => { currentParent = onValue({ type: 'array', offset, length: -1, parent: currentParent, children: [] }); @@ -908,9 +907,11 @@ export function parseTree(text: string, errors: ParseError[] = [], options?: Par onArrayEnd: (offset: number, length: number) => { currentParent.length = offset + length - currentParent.offset; currentParent = currentParent.parent; + ensurePropertyComplete(offset + length); }, onLiteralValue: (value: any, offset: number, length: number) => { onValue({ type: getLiteralNodeType(value), offset, length, parent: currentParent, value }); + ensurePropertyComplete(offset + length); }, onSeparator: (sep: string, offset: number, length: number) => { if (currentParent.type === 'property') { diff --git a/src/vs/base/test/common/json.test.ts b/src/vs/base/test/common/json.test.ts index a3b9e29cf23a4ab16e8734bee785536d8e21ee21..5a92584c1f783fced62ced028d62af38eca9a9f0 100644 --- a/src/vs/base/test/common/json.test.ts +++ b/src/vs/base/test/common/json.test.ts @@ -38,11 +38,11 @@ function assertInvalidParse(input: string, expected: any, options?: ParseOptions assert.deepEqual(actual, expected); } -function assertTree(input: string, expected: any): void { +function assertTree(input: string, expected: any, expectedErrors: number[] = []): void { var errors: ParseError[] = []; var actual = parseTree(input, errors); - assert.equal(errors.length, 0); + assert.deepEqual(errors.map(e => e.error, expected), expectedErrors); let checkParent = (node: Node) => { if (node.children) { for (let child of node.children) { @@ -313,7 +313,7 @@ suite('JSON', () => { ] }, { - type: 'property', offset: 12, length: 19, columnOffset: 15, children: [ + type: 'property', offset: 12, length: 18, columnOffset: 15, children: [ { type: 'string', offset: 12, length: 3, value: 'v' }, { type: 'array', offset: 17, length: 13, children: [ @@ -326,6 +326,27 @@ suite('JSON', () => { ] } ); + assertTree('{ "id": { "foo": { } } , }', + { + type: 'object', offset: 0, length: 27, children: [ + { + type: 'property', offset: 3, length: 20, columnOffset: 7, children: [ + { type: 'string', offset: 3, length: 4, value: 'id' }, + { + type: 'object', offset: 9, length: 14, children: [ + { + type: 'property', offset: 11, length: 10, columnOffset: 16, children: [ + { type: 'string', offset: 11, length: 5, value: 'foo' }, + { type: 'object', offset: 18, length: 3, children: [] } + ] + } + ] + } + ] + } + ] + } + , [ParseErrorCode.PropertyNameExpected, ParseErrorCode.ValueExpected]); }); test('tree: find location', () => { diff --git a/src/vs/base/test/common/jsonEdit.test.ts b/src/vs/base/test/common/jsonEdit.test.ts index 8d8b3ee7f52bcca4ffdb65352a9d7eb84e400b28..85362afad846d0e3476f433e167c53a9ba612514 100644 --- a/src/vs/base/test/common/jsonEdit.test.ts +++ b/src/vs/base/test/common/jsonEdit.test.ts @@ -83,6 +83,13 @@ suite('JSON - edits', () => { edits = setProperty(content, ['x', 'c'], 'bar', formatterOptions, () => 2); assertEdit(content, edits, '{\n "x": {\n "a": 1,\n "b": true,\n "c": "bar"\n }\n}\n'); + edits = setProperty(content, ['c'], 'bar', formatterOptions); + assertEdit(content, edits, '{\n "x": {\n "a": 1,\n "b": true\n },\n "c": "bar"\n}\n'); + + content = '{\n "a": [\n {\n } \n ] \n}'; + edits = setProperty(content, ['foo'], 'bar', formatterOptions); + assertEdit(content, edits, '{\n "a": [\n {\n } \n ],\n "foo": "bar"\n}'); + content = ''; edits = setProperty(content, ['foo', 0], 'bar', formatterOptions); assertEdit(content, edits, '{\n "foo": [\n "bar"\n ]\n}');