From 361302a292e15c98164319a0634e8a4af09e5463 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Fri, 12 Aug 2022 16:45:20 -0700 Subject: [PATCH 01/11] Add a configurable indent for sequences --- .../com/charleskorn/kaml/YamlConfiguration.kt | 2 ++ .../com/charleskorn/kaml/YamlWritingTest.kt | 23 +++++++++++++++++++ .../kotlin/com/charleskorn/kaml/YamlOutput.kt | 3 +++ 3 files changed, 28 insertions(+) diff --git a/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt b/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt index 44feb5d8..b8201d5d 100644 --- a/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt +++ b/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt @@ -31,6 +31,7 @@ package com.charleskorn.kaml * * [encodingIndentationSize]: number of spaces to use as indentation when encoding objects as YAML * * [breakScalarsAt]: maximum length of scalars when encoding objects as YAML (scalars exceeding this length will be split into multiple lines) * * [sequenceStyle]: how sequences (aka lists and arrays) should be formatted. See [SequenceStyle] for an example of each + * * [sequenceBlockIndent]: number of spaces to use as indentation for sequences, if set to block mode (0 still includes the `-` character and a space after it) */ public data class YamlConfiguration constructor( internal val encodeDefaults: Boolean = true, @@ -41,6 +42,7 @@ public data class YamlConfiguration constructor( internal val encodingIndentationSize: Int = 2, internal val breakScalarsAt: Int = 80, internal val sequenceStyle: SequenceStyle = SequenceStyle.Block, + internal val sequenceBlockIndent: Int = 0, internal val singleLineStringStyle: SingleLineStringStyle = SingleLineStringStyle.DoubleQuoted, internal val multiLineStringStyle: MultiLineStringStyle = singleLineStringStyle.multiLineStringStyle ) diff --git a/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt b/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt index 1bc61b1e..c907a933 100644 --- a/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt +++ b/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt @@ -245,6 +245,29 @@ class YamlWritingTest : DescribeSpec({ } } + context("serializing a list of integers in flow form with sequence block indent") { + val output = Yaml(configuration = YamlConfiguration(sequenceStyle = SequenceStyle.Flow, sequenceBlockIndent = 2)) + .encodeToString(ListSerializer(Int.serializer()), listOf(1, 2, 3)) + + it("returns the value serialized in the expected YAML form") { + output shouldBe "[1, 2, 3]" + } + } + + context("serializing a list of integers with sequence block indent") { + val output = Yaml(configuration = YamlConfiguration(sequenceBlockIndent = 2)) + .encodeToString(ListSerializer(Int.serializer()), listOf(1, 2, 3)) + + it("returns the value serialized in the expected YAML form") { + output shouldBe + """ + | - 1 + | - 2 + | - 3 + """.trimMargin() + } + } + context("serializing a list of nullable integers in flow form") { val output = Yaml(configuration = YamlConfiguration(sequenceStyle = SequenceStyle.Flow)) .encodeToString(ListSerializer(Int.serializer().nullable), listOf(1, null, 3)) diff --git a/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt b/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt index 847b9380..a9347146 100644 --- a/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt +++ b/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt @@ -52,6 +52,9 @@ internal class YamlOutput( ) : AbstractEncoder(), AutoCloseable { private val settings = DumpSettings.builder() .setIndent(configuration.encodingIndentationSize) + .setIndicatorIndent(configuration.sequenceBlockIndent) + // No special reason why true is conditional. Designed to be consistent with 0.46.0 of kaml + .setIndentWithIndicator(configuration.sequenceBlockIndent > 0) .setWidth(configuration.breakScalarsAt) .build() From 8a655e55a7d014a7fcc3c7d3ab1c317595ac57b5 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Fri, 12 Aug 2022 16:53:04 -0700 Subject: [PATCH 02/11] Make sequence block indent as last configuration value to maintain backwards compatibility --- .../kotlin/com/charleskorn/kaml/YamlConfiguration.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt b/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt index b8201d5d..aa6147d4 100644 --- a/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt +++ b/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt @@ -42,10 +42,10 @@ public data class YamlConfiguration constructor( internal val encodingIndentationSize: Int = 2, internal val breakScalarsAt: Int = 80, internal val sequenceStyle: SequenceStyle = SequenceStyle.Block, - internal val sequenceBlockIndent: Int = 0, internal val singleLineStringStyle: SingleLineStringStyle = SingleLineStringStyle.DoubleQuoted, - internal val multiLineStringStyle: MultiLineStringStyle = singleLineStringStyle.multiLineStringStyle -) + internal val multiLineStringStyle: MultiLineStringStyle = singleLineStringStyle.multiLineStringStyle, + internal val sequenceBlockIndent: Int = 0 + ) public enum class PolymorphismStyle { Tag, From 16b885a3f20ebf5eae8acb9255fcebe8aae56dca Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 17:30:16 -0700 Subject: [PATCH 03/11] Spotless apply --- src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt b/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt index aa6147d4..928970b1 100644 --- a/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt +++ b/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt @@ -45,7 +45,7 @@ public data class YamlConfiguration constructor( internal val singleLineStringStyle: SingleLineStringStyle = SingleLineStringStyle.DoubleQuoted, internal val multiLineStringStyle: MultiLineStringStyle = singleLineStringStyle.multiLineStringStyle, internal val sequenceBlockIndent: Int = 0 - ) +) public enum class PolymorphismStyle { Tag, From 6ec669c8c0071434ebfdb8f660065dd7b12642ed Mon Sep 17 00:00:00 2001 From: Charles Korn Date: Mon, 15 Aug 2022 13:01:28 +1000 Subject: [PATCH 04/11] Fix minor typo. --- src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt b/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt index c907a933..bbaf94ae 100644 --- a/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt +++ b/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt @@ -254,7 +254,7 @@ class YamlWritingTest : DescribeSpec({ } } - context("serializing a list of integers with sequence block indent") { + context("serializing a list of integers with sequence block indent") { val output = Yaml(configuration = YamlConfiguration(sequenceBlockIndent = 2)) .encodeToString(ListSerializer(Int.serializer()), listOf(1, 2, 3)) From 5cae1db1475fdcdd3e4b38c96b2cc3ce15b09681 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sun, 14 Aug 2022 21:47:17 -0700 Subject: [PATCH 05/11] Show sequence mode using KDoc Co-authored-by: Charles Korn --- src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt b/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt index 928970b1..ee5bc917 100644 --- a/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt +++ b/src/commonMain/kotlin/com/charleskorn/kaml/YamlConfiguration.kt @@ -31,7 +31,7 @@ package com.charleskorn.kaml * * [encodingIndentationSize]: number of spaces to use as indentation when encoding objects as YAML * * [breakScalarsAt]: maximum length of scalars when encoding objects as YAML (scalars exceeding this length will be split into multiple lines) * * [sequenceStyle]: how sequences (aka lists and arrays) should be formatted. See [SequenceStyle] for an example of each - * * [sequenceBlockIndent]: number of spaces to use as indentation for sequences, if set to block mode (0 still includes the `-` character and a space after it) + * * [sequenceBlockIndent]: number of spaces to use as indentation for sequences, if [sequenceStyle] set to [SequenceStyle.Block] */ public data class YamlConfiguration constructor( internal val encodeDefaults: Boolean = true, From 67b327256c87343c0ea20f8e143160b381876d17 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sun, 14 Aug 2022 21:50:51 -0700 Subject: [PATCH 06/11] Add clarification test to show what happens if sequence block indent is set to 0 --- .../kotlin/com/charleskorn/kaml/YamlWritingTest.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt b/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt index bbaf94ae..f318e5d8 100644 --- a/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt +++ b/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt @@ -254,6 +254,20 @@ class YamlWritingTest : DescribeSpec({ } } + context("serializing a list of integers without sequence block indent") { + val output = Yaml(configuration = YamlConfiguration(sequenceBlockIndent = 0)) + .encodeToString(ListSerializer(Int.serializer()), listOf(1, 2, 3)) + + it("returns the value serialized in the expected YAML form") { + output shouldBe + """ + |- 1 + |- 2 + |- 3 + """.trimMargin() + } + } + context("serializing a list of integers with sequence block indent") { val output = Yaml(configuration = YamlConfiguration(sequenceBlockIndent = 2)) .encodeToString(ListSerializer(Int.serializer()), listOf(1, 2, 3)) From d54316c6f55e7b2cb4b693652a98d891bb8e2341 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sun, 14 Aug 2022 22:06:43 -0700 Subject: [PATCH 07/11] Add clarification on validation --- src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt b/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt index a9347146..96fcdbdd 100644 --- a/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt +++ b/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt @@ -51,10 +51,13 @@ internal class YamlOutput( private val configuration: YamlConfiguration ) : AbstractEncoder(), AutoCloseable { private val settings = DumpSettings.builder() + // SnakeYAML validates that this value must be at least 1 .setIndent(configuration.encodingIndentationSize) + // SnakeYAML helps to validate that this value must be non-negative .setIndicatorIndent(configuration.sequenceBlockIndent) // No special reason why true is conditional. Designed to be consistent with 0.46.0 of kaml .setIndentWithIndicator(configuration.sequenceBlockIndent > 0) + // Unclear if this value is validated .setWidth(configuration.breakScalarsAt) .build() From bb68caffefe72d9912fd6f24fb5ce6a9df126250 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sun, 14 Aug 2022 22:24:33 -0700 Subject: [PATCH 08/11] Add clarification on what set indent with indicator does --- .../kotlin/com/charleskorn/kaml/YamlOutput.kt | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt b/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt index 96fcdbdd..94a49056 100644 --- a/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt +++ b/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt @@ -55,7 +55,33 @@ internal class YamlOutput( .setIndent(configuration.encodingIndentationSize) // SnakeYAML helps to validate that this value must be non-negative .setIndicatorIndent(configuration.sequenceBlockIndent) - // No special reason why true is conditional. Designed to be consistent with 0.46.0 of kaml + /* + This is required to be true to properly handle the serialization of a list of objects. + This issue becomes apparent when `sequenceBlockIndent` is 2 or more, as it causes invalid yaml. + Issue is visible if `sequenceBlockIndent` is 1, but is invalid yaml. + + Smallest reproducible test case: + + ```kotlin + @Serializable + data class Foo(val bar: String) + + Yaml(configuration = YamlConfiguration(sequenceBlockIndent = 2).encodeToString(listOf(Foo("baz")))) + + Expected output: + """ + | - bar: "baz" + """.trimMargin() + + Actual output: + """ + | - + | bar: "baz" # This is NOT valid yaml! + """.trimMargin() + ``` + + No special reason why true is conditional. Designed to be consistent with 0.46.0 of kaml + */ .setIndentWithIndicator(configuration.sequenceBlockIndent > 0) // Unclear if this value is validated .setWidth(configuration.breakScalarsAt) From 2a173de3e201cb4e945c5bc6d4ad5a631013a8ab Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sun, 14 Aug 2022 22:25:00 -0700 Subject: [PATCH 09/11] Use elvis operator :) --- src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt b/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt index 94a49056..2460c94c 100644 --- a/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt +++ b/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt @@ -181,11 +181,7 @@ internal class YamlOutput( private fun encodeComment(descriptor: SerialDescriptor, index: Int) { val commentAnno = descriptor.getElementAnnotations(index) .filterIsInstance() - .firstOrNull() - - if (commentAnno == null) { - return - } + .firstOrNull() ?: return for (line in commentAnno.lines) { emitter.emit(CommentEvent(CommentType.BLOCK, " $line", Optional.empty(), Optional.empty())) From f77d0a77fbe2dc2b139cd1101483170d3c908592 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sun, 14 Aug 2022 22:27:47 -0700 Subject: [PATCH 10/11] Add clarification that adding setting `setIndentWithIndicator` helps to solve our problems --- src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt b/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt index 2460c94c..80dccb8f 100644 --- a/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt +++ b/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt @@ -57,6 +57,7 @@ internal class YamlOutput( .setIndicatorIndent(configuration.sequenceBlockIndent) /* This is required to be true to properly handle the serialization of a list of objects. + Does not seem to have an impact on a simple top level array. This issue becomes apparent when `sequenceBlockIndent` is 2 or more, as it causes invalid yaml. Issue is visible if `sequenceBlockIndent` is 1, but is invalid yaml. @@ -79,6 +80,7 @@ internal class YamlOutput( | bar: "baz" # This is NOT valid yaml! """.trimMargin() ``` + Expected output is achieved when field is set to true No special reason why true is conditional. Designed to be consistent with 0.46.0 of kaml */ From 463f44530301fee763179d469b8d7aee76b3ce2c Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sun, 14 Aug 2022 22:58:05 -0700 Subject: [PATCH 11/11] Convert comment to test --- .../com/charleskorn/kaml/YamlWritingTest.kt | 15 ++++++++++ .../kotlin/com/charleskorn/kaml/YamlOutput.kt | 30 +------------------ 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt b/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt index f318e5d8..65e36bf5 100644 --- a/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt +++ b/src/commonTest/kotlin/com/charleskorn/kaml/YamlWritingTest.kt @@ -282,6 +282,21 @@ class YamlWritingTest : DescribeSpec({ } } + context("serializing a list of objects with sequence block indent") { + @Serializable + data class Foo(val bar: String) + + val output = Yaml(configuration = YamlConfiguration(sequenceBlockIndent = 2)) + .encodeToString(ListSerializer(Foo.serializer()), listOf(Foo("baz"))) + + it("returns the value serialized in the expected YAML form") { + output shouldBe + """ + | - bar: "baz" + """.trimMargin() + } + } + context("serializing a list of nullable integers in flow form") { val output = Yaml(configuration = YamlConfiguration(sequenceStyle = SequenceStyle.Flow)) .encodeToString(ListSerializer(Int.serializer().nullable), listOf(1, null, 3)) diff --git a/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt b/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt index 80dccb8f..66706474 100644 --- a/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt +++ b/src/jvmMain/kotlin/com/charleskorn/kaml/YamlOutput.kt @@ -55,35 +55,7 @@ internal class YamlOutput( .setIndent(configuration.encodingIndentationSize) // SnakeYAML helps to validate that this value must be non-negative .setIndicatorIndent(configuration.sequenceBlockIndent) - /* - This is required to be true to properly handle the serialization of a list of objects. - Does not seem to have an impact on a simple top level array. - This issue becomes apparent when `sequenceBlockIndent` is 2 or more, as it causes invalid yaml. - Issue is visible if `sequenceBlockIndent` is 1, but is invalid yaml. - - Smallest reproducible test case: - - ```kotlin - @Serializable - data class Foo(val bar: String) - - Yaml(configuration = YamlConfiguration(sequenceBlockIndent = 2).encodeToString(listOf(Foo("baz")))) - - Expected output: - """ - | - bar: "baz" - """.trimMargin() - - Actual output: - """ - | - - | bar: "baz" # This is NOT valid yaml! - """.trimMargin() - ``` - Expected output is achieved when field is set to true - - No special reason why true is conditional. Designed to be consistent with 0.46.0 of kaml - */ + // No special reason why true is conditional. Designed to be consistent with 0.46.0 of kaml .setIndentWithIndicator(configuration.sequenceBlockIndent > 0) // Unclear if this value is validated .setWidth(configuration.breakScalarsAt)