fix(parsing): keep a root node that begins on the document-marker line
A document-start marker scan skipped the rest of the '---' line
unconditionally, so a root node written on that same line was discarded:
a block-scalar header ('--- >' / '--- |') was dropped and its body
mis-read as a plain scalar (folded to spaces, no trailing newline), and a
same-line plain or flow node was lost entirely. The document start now
skips only trailing spaces and leaves any real same-line content for the
parser; an empty rest-of-line or a comment is still consumed, and a node
on the line below the marker is unaffected. Document end ('...') still
takes no same-line node.
Measured against the official YAML test-suite, value-level conformance
rises from 130/170 (76.5%) to 135/169 (79.9%) with no regression.
Parse-level is unchanged: these documents already parsed, just to the
wrong tree, which only the value-level metric exposes.
This commit is contained in:
parent
c888a113f2
commit
455cd07f4a
10
CHANGELOG.md
10
CHANGELOG.md
@ -23,6 +23,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- A root node that begins on the document-marker line (`--- >`, `--- |`, `--- foo`,
|
||||
`--- {a: 1}`) is no longer discarded. The marker scanner skipped the rest of the
|
||||
`---` line unconditionally, so a block-scalar header was dropped and its body was
|
||||
mis-read as a plain scalar (folded to spaces, no trailing newline) and a same-line
|
||||
plain or flow node was lost entirely. The document start now keeps any real
|
||||
same-line content for the parser, skipping only trailing spaces or a comment.
|
||||
Lifts official test-suite value-level conformance from 130/170 (76.5%) to
|
||||
135/169 (79.9%), with no regression; parse-level is unchanged because these
|
||||
documents already parsed, just to the wrong tree, which only the value-level
|
||||
metric could see.
|
||||
- A multi-line plain scalar whose value begins on its own line under a mapping key
|
||||
now folds its continuation lines instead of stopping after the first. The
|
||||
continuation check compared the next line's indent against the value's own pushed
|
||||
|
||||
@ -38,6 +38,19 @@ extension PureYAML.Parsing.Scanner {
|
||||
state.reader.advance()
|
||||
state.reader.advance()
|
||||
state.append(kind, mark: start, endMark: state.reader.mark)
|
||||
// The document's root node may begin on the marker's own line (e.g. `--- >`, `--- foo`,
|
||||
// `--- {a: 1}`, `--- !!str x`). After a document start, skip only the spaces and leave any
|
||||
// real content for the main loop to scan; an empty rest-of-line or a comment is consumed.
|
||||
// A document end (`...`) takes no same-line node, so its line is always skipped.
|
||||
if case .documentStart = kind {
|
||||
while state.reader.peek() == " " {
|
||||
state.reader.advance()
|
||||
}
|
||||
if let next = state.reader.peek(), !isLineBreak(next), next != "#" {
|
||||
state.isAtLineStart = false
|
||||
return
|
||||
}
|
||||
}
|
||||
skipLine(&state)
|
||||
}
|
||||
|
||||
|
||||
20
Tests/DocumentMarkerNodeTests.swift
Normal file
20
Tests/DocumentMarkerNodeTests.swift
Normal file
@ -0,0 +1,20 @@
|
||||
@testable import PureYAML
|
||||
import Testing
|
||||
|
||||
@Suite("Document marker root nodes")
|
||||
struct DocumentMarkerNodeTests {
|
||||
@Test("A block scalar header on the document-marker line is recognized, not discarded")
|
||||
func test_blockScalarHeaderOnDocumentMarkerLine() throws {
|
||||
// `--- >` / `--- |`: the marker scanner used to skip the rest of the line, dropping the
|
||||
// block header so the body was mis-read as a plain scalar (folded, no trailing newline).
|
||||
#expect(try PureYAML.parse("--- >\n a\n b\n") == .string("a b\n"))
|
||||
#expect(try PureYAML.parse("--- |\n a\n b\n") == .string("a\nb\n"))
|
||||
}
|
||||
|
||||
@Test("A scalar root node may begin on the document-marker line")
|
||||
func test_scalarRootNodeOnDocumentMarkerLine() throws {
|
||||
#expect(try PureYAML.parse("--- folded text\n") == .string("folded text"))
|
||||
// A node still on its own line below the marker keeps working.
|
||||
#expect(try PureYAML.parse("---\nplain text\n") == .string("plain text"))
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user