PureYAML/Tests/InlineKeyPropertyAnchorTests.swift
Mihaela M c858339307 fix(parsing): bind an inline first-key property to the key
A property written inline before a block mapping's first key (`&a key: v`) was
attached to the whole mapping, so an anchor registered only when the mapping
ended, too late for an alias inside one of the mapping's values to resolve.

The YAML grammar requires a block collection's own properties to be followed by
a line break (`s-l+block-collection`), so a property on the first key's line
belongs to the key, not the collection. The mapping now keeps only a property
written on its own line above the first key; an inline one is threaded back to
the first pair, where the key parses it and an anchor registers with the key.

Fixes yaml-test-suite 2SXE (`&a:` and `&a` are distinct anchors, since a name
includes a trailing `:`) and HMQ5 (a key carrying both a tag and an anchor).
Raises parse-level conformance to 308/333 (92.5%) and value-level to 201/201
(100.0%), with the should-error rate unchanged.
2026-06-29 03:24:30 +02:00

35 lines
1.9 KiB
Swift

@testable import PureYAML
import Testing
@Suite("An inline property before the first key binds to the key, not the mapping")
struct InlineKeyPropertyAnchorTests {
/// A property written inline before the first key (`&k key: v`) anchors that key, so the anchor
/// registers with the key and resolves early, before the enclosing mapping ends. Binding it to
/// the mapping would register only at the mapping's end, too late for an alias inside a value.
@Test("An inline anchor on the first key resolves from a later value")
func test_inlineFirstKeyAnchorResolves() throws {
let mapping = try requireMapping(PureYAML.parse("&k key: v\nx: *k\n"))
#expect(mapping?["key"] == .string("v"))
#expect(mapping?["x"] == .string("key"))
}
/// yaml-test-suite 2SXE: anchor names include `:` (a valid `ns-anchor-char`), so `&a:` and `&a`
/// are distinct anchors. The alias `*a:` resolves to the `&a:`-anchored key `key`, not the
/// `&a`-anchored value, and the inline anchor binds to the key rather than the whole mapping.
@Test("Distinct anchor names differing only by a trailing colon resolve independently")
func test_anchorNamesIncludingColon() throws {
let mapping = try requireMapping(PureYAML.parse("&a: key: &a value\nfoo:\n *a:\n"))
#expect(mapping?["key"] == .string("value"))
#expect(mapping?["foo"] == .string("key"))
}
/// yaml-test-suite HMQ5: a key may carry both a tag and an anchor (`!!str &a1 "foo"`); the anchor
/// registers the resolved key value so a later `*a1` comes back as that value.
@Test("A first key carrying both a tag and an anchor registers for its alias")
func test_inlineFirstKeyTagAndAnchor() throws {
let mapping = try requireMapping(PureYAML.parse("!!str &a1 \"foo\":\n !!str bar\n&a2 baz : *a1\n"))
#expect(mapping?["foo"] == .string("bar"))
#expect(mapping?["baz"] == .string("foo"))
}
}