Skip to content

Commit e2a2aea

Browse files
authored
feat: add YamlScalar.plain to distinguish plain and quoted scalars (#12)
1 parent a0e62b6 commit e2a2aea

3 files changed

Lines changed: 46 additions & 5 deletions

File tree

src/commonMain/kotlin/com/charleskorn/kaml/YamlNode.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public sealed class YamlNode(
4444
public data class YamlScalar(
4545
val content: String,
4646
override val path: YamlPath,
47+
val plain: Boolean = true,
4748
) : YamlNode(path) {
4849
override fun equivalentContentTo(other: YamlNode): Boolean = other is YamlScalar && this.content == other.content
4950

@@ -158,6 +159,11 @@ public data class YamlScalar(
158159

159160
override fun withPath(newPath: YamlPath): YamlScalar = this.copy(path = newPath)
160161

162+
// equals/hashCode intentionally exclude plain: the scalar style is a presentation detail and must not affect content equality.
163+
override fun equals(other: Any?): Boolean = other is YamlScalar && content == other.content && path == other.path
164+
165+
override fun hashCode(): Int = 31 * content.hashCode() + path.hashCode()
166+
161167
override fun toString(): String = "scalar @ $path : $content"
162168
}
163169

src/commonMain/kotlin/com/charleskorn/kaml/YamlNodeReader.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ internal class YamlNodeReader(
8080
if ((event.value == "null" || event.value == "" || event.value == "~") && event.plain) {
8181
return YamlNull(path)
8282
} else {
83-
return YamlScalar(event.value, path)
83+
return YamlScalar(event.value, path, plain = event.plain)
8484
}
8585
}
8686

@@ -121,8 +121,9 @@ internal class YamlNodeReader(
121121

122122
else -> {
123123
val keyLocation = parser.peekEvent(path).location
124-
val key = readMapKey(path)
125-
val keyNode = YamlScalar(key, path.withMapElementKey(key, keyLocation))
124+
val keyEvent = readMapKey(path)
125+
val key = keyEvent.value
126+
val keyNode = YamlScalar(key, path.withMapElementKey(key, keyLocation), plain = keyEvent.plain)
126127

127128
val valueLocation = parser.peekEvent(keyNode.path).location
128129
val valuePath = if (isMerge(keyNode)) path.withMerge(valueLocation) else keyNode.path.withMapElementValue(valueLocation)
@@ -141,7 +142,7 @@ internal class YamlNodeReader(
141142
}
142143
}
143144

144-
private fun readMapKey(path: YamlPath): String {
145+
private fun readMapKey(path: YamlPath): ScalarEvent {
145146
val event = parser.peekEvent(path)
146147

147148
when (event.eventId) {
@@ -154,7 +155,7 @@ internal class YamlNodeReader(
154155
throw nonScalarMapKeyException(path, event)
155156
}
156157

157-
return scalarEvent.value
158+
return scalarEvent
158159
}
159160

160161
else -> {

src/jvmTest/kotlin/com/charleskorn/kaml/YamlNodeReaderTest.kt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,40 @@ class YamlNodeReaderTest :
6262
}
6363
}
6464

65+
mapOf(
66+
"0.10" to true,
67+
"hello" to true,
68+
"'0.10'" to false,
69+
""""0.10"""" to false,
70+
"'hello'" to false,
71+
""""hello"""" to false,
72+
).forEach { (input, expectedPlain) ->
73+
context("given the scalar '$input'") {
74+
describe("parsing that input") {
75+
val parser = YamlParser(input)
76+
val result = YamlNodeReader(parser).read()
77+
78+
it("exposes whether the scalar was written in plain style") {
79+
(result as YamlScalar).plain shouldBe expectedPlain
80+
}
81+
}
82+
}
83+
}
84+
85+
describe("plain and quoted scalars with the same content") {
86+
val plainScalar = YamlNodeReader(YamlParser("0.10")).read() as YamlScalar
87+
val quotedScalar = YamlNodeReader(YamlParser("'0.10'")).read() as YamlScalar
88+
89+
it("preserve the same content") {
90+
plainScalar.content shouldBe quotedScalar.content
91+
}
92+
93+
it("can be told apart via plain") {
94+
plainScalar.plain shouldBe true
95+
quotedScalar.plain shouldBe false
96+
}
97+
}
98+
6599
// https://yaml.org/spec/1.2/spec.html#id2793979 is useful reference here, as is
66100
// https://yaml-multiline.info/
67101
mapOf(

0 commit comments

Comments
 (0)