PureYAML/Tests/InlineNestedMappingTests.swift
Mihaela M 735767ced9 fix(parsing): reject inline nested block mappings
Block style permits only one mapping pair per line, so a scalar followed
by ':' after a block-level value on the same line (a: b: c, a: 'b': c,
x: { y: z }in: valid, or trailing content after a quoted value) is not a
new key but a forbidden inline nested mapping. The scanner synthesized an
implicit key for any scalar followed by ':', regardless of position, so
these parsed as nested mappings instead of failing.

The scanner now records when a line already holds a block-level mapping
pair and suppresses a further implicit key on that line, in plain and
quoted scalars alike. The flag is set only for an implicit-key ':' (one
preceded by its key on the same line): a ':' that opens its line is an
explicit- or null-key value indicator, whose value may be a compact
mapping (? k then : a: 1), so that, flow mappings, next-line nesting, and
colons inside scalars stay valid.

Measured against the official YAML test-suite, parse-level conformance
rises from 256/333 (76.9%) to 260/333 (78.1%) with no regression.
2026-06-27 18:28:57 +02:00

42 lines
1.8 KiB
Swift

@testable import PureYAML
import Testing
@Suite("Inline nested block mappings are rejected")
struct InlineNestedMappingTests {
@Test("A second mapping pair on a block line is rejected", arguments: [
"a: b: c: d\n", // a plain value followed by another key
"a: 'b': c\n", // a quoted value followed by another key
"key2: \"q\" no key: nor value\n", // trailing content after a quoted value
"x: { y: z }in: valid\n", // trailing content after a flow value
])
func test_inlineNestedMappingRejected(_ yaml: String) throws {
#expect(throws: PureYAML.Parsing.ParseError.self) {
try PureYAML.parse(yaml)
}
}
@Test("Mappings spread across lines, and flow mappings, stay valid", arguments: [
"a: b\nc: d\n", // two pairs on separate lines
"a:\n b: c\n", // a nested mapping on the next line
"- key: value\n", // a sequence item that is a mapping
"{a: b, c: d}\n", // a flow mapping with several pairs on one line
"a: http://x\n", // a colon inside a plain scalar value
])
func test_validMappingsStillParse(_ yaml: String) throws {
_ = try PureYAML.parse(yaml)
}
@Test("An explicit key's value may be a compact mapping on the value line")
func test_explicitKeyCompactMappingValue() throws {
// The `:` opens the line, so it is an explicit-key value indicator whose value may be a
// compact block mapping, unlike an implicit key's same-line value.
let value = try PureYAML.parse("? k\n: minLength: 14\n pattern: x\n")
#expect(value == .mapping(.init([
.init(keyNode: .string("k"), value: .mapping(.init([
.init(key: "minLength", value: .int(14)),
.init(key: "pattern", value: .string("x")),
]))),
])))
}
}