Skip to content

Commit 53456f5

Browse files
committed
Parse errors make parsed tree useless. Fixes #32
1 parent 83b7f3d commit 53456f5

File tree

2 files changed

+74
-9
lines changed

2 files changed

+74
-9
lines changed

src/impl/parser.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ export function parseTree(text: string, errors: ParseError[] = [], options: Pars
233233
currentParent.children!.push({ type: 'string', value: name, offset, length, parent: currentParent });
234234
},
235235
onObjectEnd: (offset: number, length: number) => {
236+
ensurePropertyComplete(offset + length); // in case of a missing value for a property: make sure property is complete
237+
236238
currentParent.length = offset + length - currentParent.offset;
237239
currentParent = currentParent.parent!;
238240
ensurePropertyComplete(offset + length);

src/test/json.test.ts

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function assertTree(input: string, expected: any, expectedErrors: ParseError[] =
6464
};
6565
checkParent(actual);
6666

67-
assert.deepEqual(actual, expected);
67+
assert.deepEqual(actual, expected, JSON.stringify(actual));
6868
}
6969

7070
interface VisitorCallback {
@@ -97,10 +97,10 @@ function assertVisit(input: string, expected: VisitorCallback[], expectedErrors:
9797
errors.push({ error, offset, length, startLine, startCharacter })
9898
}
9999
}, {
100-
disallowComments
101-
});
100+
disallowComments
101+
});
102102
assert.deepEqual(errors, expectedErrors);
103-
assert.deepEqual(actuals, expected);
103+
assert.deepEqual(actuals, expected, JSON.stringify(actuals));
104104
}
105105

106106
function assertNodeAtLocation(input: Node, segments: Segment[], expected: any) {
@@ -428,9 +428,9 @@ suite('JSON', () => {
428428
}
429429
]
430430
}, [
431-
{ error: ParseErrorCode.PropertyNameExpected, offset: 26, length: 1 },
432-
{ error: ParseErrorCode.ValueExpected, offset: 26, length: 1 }
433-
]);
431+
{ error: ParseErrorCode.PropertyNameExpected, offset: 26, length: 1 },
432+
{ error: ParseErrorCode.ValueExpected, offset: 26, length: 1 }
433+
]);
434434
});
435435

436436
test('visit: object', () => {
@@ -484,8 +484,8 @@ suite('JSON', () => {
484484
{ id: 'onObjectProperty', text: '"foo"', startLine: 0, startCharacter: 10, arg: 'foo' },
485485
{ id: 'onSeparator', text: ':', startLine: 0, startCharacter: 15, arg: ':' },
486486
{ id: 'onComment', text: '//f', startLine: 0, startCharacter: 17 },
487-
{ id: 'onLiteralValue', text: '"bar"', startLine: 1, startCharacter: 0, arg: 'bar' },
488-
{ id: 'onObjectEnd', text: '}', startLine: 1, startCharacter: 6 },
487+
{ id: 'onLiteralValue', text: '"bar"', startLine: 1, startCharacter: 0, arg: 'bar' },
488+
{ id: 'onObjectEnd', text: '}', startLine: 1, startCharacter: 6 },
489489
]);
490490
assertVisit('/* g\r\n */ { "foo": //f\n"bar" }', [
491491
{ id: 'onComment', text: '/* g\r\n */', startLine: 0, startCharacter: 0 },
@@ -511,6 +511,69 @@ suite('JSON', () => {
511511
true);
512512
});
513513

514+
test('visit: incomplete', () => {
515+
assertVisit('{"prop1":"foo","prop2":"foo2","prop3":{"prp1":{""}}}', [
516+
{ id: 'onObjectBegin', text: "{", startLine: 0, startCharacter: 0 },
517+
{ id: 'onObjectProperty', text: '"prop1"', startLine: 0, startCharacter: 1, arg: "prop1" },
518+
{ id: 'onSeparator', text: ":", startLine: 0, startCharacter: 8, arg: ":" },
519+
{ id: 'onLiteralValue', text: '"foo"', startLine: 0, startCharacter: 9, arg: "foo" },
520+
{ id: 'onSeparator', text: ",", startLine: 0, startCharacter: 14, arg: "," },
521+
{ id: 'onObjectProperty', text: '"prop2"', startLine: 0, startCharacter: 15, arg: "prop2" },
522+
{ id: 'onSeparator', text: ":", startLine: 0, startCharacter: 22, arg: ":" },
523+
{ id: 'onLiteralValue', text: '"foo2"', startLine: 0, startCharacter: 23, arg: "foo2" },
524+
{ id: 'onSeparator', text: ",", startLine: 0, startCharacter: 29, arg: "," },
525+
{ id: 'onObjectProperty', text: '"prop3"', startLine: 0, startCharacter: 30, arg: "prop3" },
526+
{ id: 'onSeparator', text: ":", startLine: 0, startCharacter: 37, arg: ":" },
527+
{ id: 'onObjectBegin', text: "{", startLine: 0, startCharacter: 38 },
528+
{ id: 'onObjectProperty', text: '"prp1"', startLine: 0, startCharacter: 39, arg: "prp1" },
529+
{ id: 'onSeparator', text: ":", startLine: 0, startCharacter: 45, arg: ":" },
530+
{ id: 'onObjectBegin', text: "{", startLine: 0, startCharacter: 46 },
531+
{ id: 'onObjectProperty', text: '""', startLine: 0, startCharacter: 47, arg: "" },
532+
{ id: 'onObjectEnd', text: "}", startLine: 0, startCharacter: 49 },
533+
{ id: 'onObjectEnd', text: "}", startLine: 0, startCharacter: 50 },
534+
{ id: 'onObjectEnd', text: "}", startLine: 0, startCharacter: 51 }
535+
], [{ error: ParseErrorCode.ColonExpected, offset: 49, length: 1, startLine: 0, startCharacter: 49 }]);
536+
537+
assertTree('{"prop1":"foo","prop2":"foo2","prop3":{"prp1":{""}}}', {
538+
type: 'object', offset: 0, length: 52, children: [
539+
{
540+
type: 'property', offset: 1, length: 13, children: [
541+
{ type: 'string', value: 'prop1', offset: 1, length: 7 },
542+
{ type: 'string', offset: 9, length: 5, value: 'foo' }
543+
], colonOffset: 8
544+
}, {
545+
type: 'property', offset: 15, length: 14, children: [
546+
{ type: 'string', value: 'prop2', offset: 15, length: 7 },
547+
{ type: 'string', offset: 23, length: 6, value: 'foo2' }
548+
], colonOffset: 22
549+
},
550+
{
551+
type: 'property', offset: 30, length: 21, children: [
552+
{ type: 'string', value: 'prop3', offset: 30, length: 7 },
553+
{
554+
type: 'object', offset: 38, length: 13, children: [
555+
{
556+
type: 'property', offset: 39, length: 11, children: [
557+
{ type: 'string', value: 'prp1', offset: 39, length: 6 },
558+
{
559+
type: 'object', offset: 46, length: 4, children: [
560+
{
561+
type: 'property', offset: 47, length: 3, children: [
562+
{ type: 'string', value: '', offset: 47, length: 2 },
563+
]
564+
}
565+
]
566+
}
567+
], colonOffset: 45
568+
}
569+
]
570+
}
571+
], colonOffset: 37
572+
}
573+
]
574+
}, [{ error: ParseErrorCode.ColonExpected, offset: 49, length: 1 }])
575+
});
576+
514577
test('tree: find location', () => {
515578
let root = parseTree('{ "key1": { "key11": [ "val111", "val112" ] }, "key2": [ { "key21": false, "key22": 221 }, null, [{}] ] }');
516579
assertNodeAtLocation(root, ['key1'], { key11: ['val111', 'val112'] });

0 commit comments

Comments
 (0)