-
Notifications
You must be signed in to change notification settings - Fork 72
Fix multiline scalar serialization round-trips #414
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -215,8 +215,13 @@ func (s *Serializer) node(node *Node, tail string) { | |
| style = LITERAL_SCALAR_STYLE | ||
| case node.Style&FoldedStyle != 0: | ||
| style = FOLDED_SCALAR_STYLE | ||
| case strings.Contains(value, "\n"): | ||
| case shouldUseLiteralStyle(value): | ||
| style = LITERAL_SCALAR_STYLE | ||
| case strings.Contains(value, "\n"): | ||
| // Multiline but not literal-eligible (e.g. first content line | ||
| // starts with a tab): a block scalar would not round-trip, so | ||
| // emit a double-quoted scalar instead. | ||
| style = DOUBLE_QUOTED_SCALAR_STYLE | ||
| case forceQuoting: | ||
| style = s.quotePreference.ScalarStyle() | ||
| } | ||
|
Comment on lines
+218
to
227
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm unsure I saw test for the priority of shoulduseLiteral or new line against forceQuoting ? Do you think you could add tests for this? |
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -2739,6 +2739,78 @@ func TestSetIndent(t *testing.T) { | |||||
| assert.Equal(t, "a:\n b:\n c: d\n", buf.String()) | ||||||
| } | ||||||
|
|
||||||
| // A block scalar whose first non-empty line is indented needs an explicit | ||||||
| // indentation indicator, and that indicator is relative to the parent node's | ||||||
| // indentation, not BestIndent. | ||||||
| // This covers both the missing-indicator case (a leading empty line followed | ||||||
| // by indented content) and the wrong-value case (a scalar nested in a block | ||||||
| // sequence item, which only adds two columns of indentation). | ||||||
| // See https://github.com/yaml/go-yaml/issues/76 | ||||||
| // and https://github.com/go-yaml/yaml/issues/1071 | ||||||
| func TestBlockScalarIndentIndicatorRoundTrip(t *testing.T) { | ||||||
| type params struct { | ||||||
| Description string `yaml:"description"` | ||||||
| } | ||||||
| type spec struct { | ||||||
| Parameters []params `yaml:"parameters"` | ||||||
| } | ||||||
|
|
||||||
| // Includes indents at and beyond the 1..9 indicator range (9, 10) to | ||||||
| // cover clamping of the indentation indicator. | ||||||
| for _, indent := range []int{0, 1, 2, 3, 4, 8, 9, 10} { | ||||||
| for _, description := range []string{ | ||||||
| " a\nb", | ||||||
| " a\nb", | ||||||
| " a\n b", | ||||||
| "\n indented\nregular", | ||||||
| "\n\n more indented\nregular", | ||||||
| } { | ||||||
| in := spec{Parameters: []params{{Description: description}}} | ||||||
|
|
||||||
| var buf bytes.Buffer | ||||||
| enc := yaml.NewEncoder(&buf) | ||||||
| if indent > 0 { | ||||||
| enc.SetIndent(indent) | ||||||
| } | ||||||
| assert.NoError(t, enc.Encode(&in)) | ||||||
| assert.NoError(t, enc.Close()) | ||||||
|
|
||||||
| var out spec | ||||||
| err := yaml.Unmarshal(buf.Bytes(), &out) | ||||||
| assert.NoErrorf( | ||||||
| t, err, "indent %d, encoded as:\n%s", indent, buf.String()) | ||||||
| assert.DeepEqualf( | ||||||
| t, in, out, "indent %d, encoded as:\n%s", indent, buf.String()) | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
Comment on lines
+2742
to
+2786
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can see the loop on indentation, but could you try using the .yanl test file to validatw them. The yaml test suite is intended to be reused on other projects using YAML. We would appreciate |
||||||
|
|
||||||
| // A multiline scalar whose first content line begins with a tab cannot be | ||||||
| // expressed as a block scalar (block indentation is spaces only), so it must | ||||||
| // be emitted double-quoted and still round-trip exactly. | ||||||
| // See https://github.com/yaml/go-yaml/issues/383 | ||||||
| func TestTabLeadingScalarRoundTrip(t *testing.T) { | ||||||
| type doc struct { | ||||||
| Text string `yaml:"text"` | ||||||
| } | ||||||
|
|
||||||
| for _, text := range []string{ | ||||||
| "\tthis\nis\nmultiline", | ||||||
| "\tB\n\tC\n", | ||||||
| "\n\tindented by tab\nregular", | ||||||
| "first\n\tsecond\n", // tab on a later line: stays literal | ||||||
| } { | ||||||
| in := doc{Text: text} | ||||||
| out, err := yaml.Marshal(&in) | ||||||
| assert.NoError(t, err) | ||||||
|
|
||||||
| var back doc | ||||||
| assert.NoErrorf(t, yaml.Unmarshal(out, &back), | ||||||
| "encoded as:\n%s", out) | ||||||
| assert.DeepEqualf(t, in, back, "encoded as:\n%s", out) | ||||||
| } | ||||||
| } | ||||||
|
Comment on lines
+2788
to
+2812
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't we express this in one of the .yaml test file ? |
||||||
|
|
||||||
| func TestSortedOutput(t *testing.T) { | ||||||
| order := []any{ | ||||||
| false, | ||||||
|
|
@@ -2984,27 +3056,27 @@ func TestScalarStyleWithTabs(t *testing.T) { | |||||
| }, | ||||||
| { | ||||||
| "\tThis starts with tab\nand is long enough\nfor literal style", | ||||||
| "|-\n \tThis starts with tab\n and is long enough\n for literal style\n", | ||||||
| "\"\\tThis starts with tab\\nand is long enough\\nfor literal style\"\n", | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here and everwhere. Please use raw string literal for readability
Suggested change
|
||||||
| "Multiline starting with tab", | ||||||
| }, | ||||||
| { | ||||||
| "\tB\n\tC\n", | ||||||
| "|\n \tB\n \tC\n", | ||||||
| "\"\\tB\\n\\tC\\n\"\n", | ||||||
| "Tab B newline tab C newline", | ||||||
| }, | ||||||
| { | ||||||
| "\ta\n", | ||||||
| "|\n \ta\n", | ||||||
| "\"\\ta\\n\"\n", | ||||||
| "Tab + char + newline", | ||||||
| }, | ||||||
| { | ||||||
| "\thello\n", | ||||||
| "|\n \thello\n", | ||||||
| "\"\\thello\\n\"\n", | ||||||
| "Tab + text + newline", | ||||||
| }, | ||||||
| { | ||||||
| "\t\nhello", | ||||||
| "|-\n \t\n hello\n", | ||||||
| "\"\\t\\nhello\"\n", | ||||||
| "Tab + newline + text", | ||||||
| }, | ||||||
| } | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use what I had suggested in another PR
#393 (comment)