From 8b0a3a4c46554030516be24f9a8d1ab95f841547 Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Wed, 5 Oct 2022 10:07:44 +0300 Subject: [PATCH] fix: Set correct node-end position for block collections with comments (#413) --- src/compose/resolve-block-map.ts | 7 ++++-- src/compose/resolve-block-seq.ts | 10 ++++----- tests/doc/errors.js | 38 ++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/compose/resolve-block-map.ts b/src/compose/resolve-block-map.ts index 149a1fdf..8e3a495a 100644 --- a/src/compose/resolve-block-map.ts +++ b/src/compose/resolve-block-map.ts @@ -21,6 +21,7 @@ export function resolveBlockMap( if (ctx.atRoot) ctx.atRoot = false let offset = bm.offset + let commentEnd: number | null = null for (const collItem of bm.items) { const { start, key, sep, value } = collItem @@ -45,7 +46,7 @@ export function resolveBlockMap( onError(offset, 'BAD_INDENT', startColMsg) } if (!keyProps.anchor && !keyProps.tag && !sep) { - // TODO: assert being at last item? + commentEnd = keyProps.end if (keyProps.comment) { if (map.comment) map.comment += '\n' + keyProps.comment else map.comment = keyProps.comment @@ -128,6 +129,8 @@ export function resolveBlockMap( } } - map.range = [bm.offset, offset, offset] + if (commentEnd && commentEnd < offset) + onError(commentEnd, 'IMPOSSIBLE', 'Map comment with trailing content') + map.range = [bm.offset, offset, commentEnd ?? offset] return map as YAMLMap.Parsed } diff --git a/src/compose/resolve-block-seq.ts b/src/compose/resolve-block-seq.ts index 089fa148..a23cf248 100644 --- a/src/compose/resolve-block-seq.ts +++ b/src/compose/resolve-block-seq.ts @@ -15,6 +15,7 @@ export function resolveBlockSeq( if (ctx.atRoot) ctx.atRoot = false let offset = bs.offset + let commentEnd: number | null = null for (const { start, value } of bs.items) { const props = resolveProps(start, { indicator: 'seq-item-ind', @@ -23,30 +24,29 @@ export function resolveBlockSeq( onError, startOnNewline: true }) - offset = props.end if (!props.found) { if (props.anchor || props.tag || value) { if (value && value.type === 'block-seq') onError( - offset, + props.end, 'BAD_INDENT', 'All sequence items must start at the same column' ) else onError(offset, 'MISSING_CHAR', 'Sequence item without - indicator') } else { - // TODO: assert being at last item? + commentEnd = props.end if (props.comment) seq.comment = props.comment continue } } const node = value ? composeNode(ctx, value, props, onError) - : composeEmptyNode(ctx, offset, start, null, props, onError) + : composeEmptyNode(ctx, props.end, start, null, props, onError) if (ctx.schema.compat) flowIndentCheck(bs.indent, value, onError) offset = node.range[2] seq.items.push(node) } - seq.range = [bs.offset, offset, offset] + seq.range = [bs.offset, offset, commentEnd ?? offset] return seq as YAMLSeq.Parsed } diff --git a/tests/doc/errors.js b/tests/doc/errors.js index b99ced17..00fe35ad 100644 --- a/tests/doc/errors.js +++ b/tests/doc/errors.js @@ -140,6 +140,44 @@ describe('block collections', () => { `) expect(doc.errors).toMatchObject([]) }) + + test('key after long comment on block map (eemeli/yaml#413)', () => { + const doc = YAML.parseDocument(source` + one: + sub: a + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + two: b + `) + expect(doc.errors).toMatchObject([]) + }) + + test('key after long comment on block seq (eemeli/yaml#413)', () => { + const doc = YAML.parseDocument(source` + one: + - a + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + # large block of text, large block of text, large block of text, large block of text, large block of text, + two: b + `) + expect(doc.errors).toMatchObject([]) + }) }) describe('flow collections', () => {