Skip to content

Commit fa65881

Browse files
authored
Merge pull request #887 from dougbu/dougbu/blank.lines.886
Handle blank lines in `Yaml.Text()`
2 parents 7daf14c + c04446e commit fa65881

File tree

3 files changed

+141
-18
lines changed

3 files changed

+141
-18
lines changed

YamlDotNet.Test/Serialization/SerializationTests.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ public void DeserializeWithGapsBetweenKeys()
253253
{
254254
var yamlReader = new StringReader(@"Text: >
255255
Some Text.
256-
256+
257257
Value: foo");
258258
var result = Deserializer.Deserialize(yamlReader);
259259

@@ -1203,10 +1203,10 @@ public void BackreferencesAreMergedWithMappings()
12031203
public void MergingDoesNotProduceDuplicateAnchors()
12041204
{
12051205
var parser = new MergingParser(Yaml.ParserForText(@"
1206-
anchor: &default
1206+
anchor: &default
12071207
key1: &myValue value1
12081208
key2: value2
1209-
alias:
1209+
alias:
12101210
<<: *default
12111211
key2: Overriding key2
12121212
key3: value3
@@ -1234,24 +1234,24 @@ public void ExampleFromSpecificationIsHandledCorrectly()
12341234
- &LEFT { x: 0, y: 2 }
12351235
- &BIG { r: 10 }
12361236
- &SMALL { r: 1 }
1237-
1237+
12381238
# All the following maps are equal:
12391239
results:
12401240
- # Explicit keys
12411241
x: 1
12421242
y: 2
12431243
r: 10
12441244
label: center/big
1245-
1245+
12461246
- # Merge one map
12471247
<< : *CENTER
12481248
r: 10
12491249
label: center/big
1250-
1250+
12511251
- # Merge multiple maps
12521252
<< : [ *CENTER, *BIG ]
12531253
label: center/big
1254-
1254+
12551255
- # Override
12561256
<< : [ *BIG, *LEFT, *SMALL ]
12571257
x: 1
@@ -1287,10 +1287,10 @@ public void MergeNestedReferenceCorrectly()
12871287
derived1:
12881288
<<: *level1
12891289
key: D1
1290-
derived2:
1290+
derived2:
12911291
<<: *level2
12921292
key: D2
1293-
derived3:
1293+
derived3:
12941294
<<: [ *level1, *level2 ]
12951295
key: D3
12961296
"));
@@ -2169,29 +2169,29 @@ public void ShouldIndentSequences()
21692169
[Fact]
21702170
public void ExampleFromSpecificationIsHandledCorrectlyWithLateDefine()
21712171
{
2172-
var parser = new MergingParser(Yaml.ParserForText(@"
2172+
var parser = new MergingParser(Yaml.ParserForText(@"
21732173
# All the following maps are equal:
21742174
results:
21752175
- # Explicit keys
21762176
x: 1
21772177
y: 2
21782178
r: 10
21792179
label: center/big
2180-
2180+
21812181
- # Merge one map
21822182
<< : *CENTER
21832183
r: 10
21842184
label: center/big
2185-
2185+
21862186
- # Merge multiple maps
21872187
<< : [ *CENTER, *BIG ]
21882188
label: center/big
2189-
2189+
21902190
- # Override
21912191
<< : [ *BIG, *LEFT, *SMALL ]
21922192
x: 1
21932193
label: center/big
2194-
2194+
21952195
obj:
21962196
- &CENTER { x: 1, y: 2 }
21972197
- &LEFT { x: 0, y: 2 }

YamlDotNet.Test/Yaml.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ public static string Text(string yamlText)
9090
{
9191
var lines = yamlText
9292
.Split('\n')
93-
.Select(l => l.TrimEnd('\r', '\n'))
94-
.SkipWhile(l => l.Trim(' ', '\t').Length == 0)
93+
.Select(l => l.TrimEnd())
94+
.SkipWhile(l => l.Length == 0)
9595
.ToList();
9696

97-
while (lines.Count > 0 && lines[lines.Count - 1].Trim(' ', '\t').Length == 0)
97+
while (lines.Count > 0 && lines[lines.Count - 1].Length == 0)
9898
{
9999
lines.RemoveAt(lines.Count - 1);
100100
}
@@ -107,8 +107,15 @@ public static string Text(string yamlText)
107107
throw new ArgumentException("Invalid indentation");
108108
}
109109

110+
var indentation = indent.Groups[1].Length;
110111
lines = lines
111-
.Select(l => l.Substring(indent.Groups[1].Length))
112+
.Select((l, num) => l.Length == 0 ?
113+
// Blank lines don't need to be indented.
114+
string.Empty :
115+
l.TakeWhile(c => c == ' ' || c == '\t').Count() < indentation ?
116+
// However, other lines must be indented at least as much as the first line.
117+
throw new ArgumentException($"Incorrectly indented line '{l}', #{num}.", nameof(yamlText)) :
118+
l.Substring(indentation))
112119
.ToList();
113120
}
114121

YamlDotNet.Test/YamlTests.cs

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// This file is part of YamlDotNet - A .NET library for YAML.
2+
// Copyright (c) Antoine Aubry and contributors
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy of
5+
// this software and associated documentation files (the "Software"), to deal in
6+
// the Software without restriction, including without limitation the rights to
7+
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8+
// of the Software, and to permit persons to whom the Software is furnished to do
9+
// so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in all
12+
// copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
// SOFTWARE.
21+
22+
using System;
23+
using FluentAssertions;
24+
using Xunit;
25+
26+
namespace YamlDotNet.Test
27+
{
28+
public class YamlTests
29+
{
30+
private const string SingleLine = "object:";
31+
private const string LeadingBlankLines = @"
32+
33+
34+
object:";
35+
private const string LeadingBlankLinesWithWhitespace = @"
36+
37+
38+
object:";
39+
private const string TrailingBlankLines = @"object:
40+
41+
42+
";
43+
private const string TrailingBlankLinesWithWhitespace = @"object:
44+
45+
46+
";
47+
48+
private const string Lines = @"this:
49+
that:
50+
theOtherThing:";
51+
private const string IndentedLines = @" this:
52+
that:
53+
theOtherThing:";
54+
55+
private const string NestedLines = @"Map1:
56+
Map2:
57+
- entry 1
58+
- entry 2
59+
- entry 3";
60+
private const string IndentedNestedLines = @" Map1:
61+
Map2:
62+
- entry 1
63+
- entry 2
64+
- entry 3";
65+
66+
private const string SomeBlankLines = @"this:
67+
68+
that:
69+
70+
71+
theOtherThing:";
72+
private const string SomeBlankLinesWithWhitespace = @"this:
73+
74+
that:
75+
76+
77+
theOtherThing:";
78+
79+
[Theory]
80+
[InlineData(SingleLine, SingleLine)]
81+
[InlineData(LeadingBlankLines, SingleLine)]
82+
[InlineData(LeadingBlankLinesWithWhitespace, SingleLine)]
83+
[InlineData(TrailingBlankLines, SingleLine)]
84+
[InlineData(TrailingBlankLinesWithWhitespace, SingleLine)]
85+
[InlineData(Lines, Lines)]
86+
[InlineData(IndentedLines, Lines)]
87+
[InlineData(NestedLines, NestedLines)]
88+
[InlineData(IndentedNestedLines, NestedLines)]
89+
[InlineData(SomeBlankLines, SomeBlankLines)]
90+
[InlineData(SomeBlankLinesWithWhitespace, SomeBlankLines)]
91+
public void TextProducesExpectedOutput(string text, string expectedText)
92+
{
93+
expectedText = expectedText.NormalizeNewLines();
94+
var result = Yaml.Text(text);
95+
96+
result.NormalizeNewLines().Should().Be(expectedText);
97+
}
98+
99+
[Fact]
100+
public void TextThrowsArgumentOutOfRangeExceptionForInsuffientIndentation()
101+
{
102+
const string BadlyIndentedLines = @" this:
103+
that:
104+
theOtherThing:";
105+
var expectedMessage =
106+
#if NETFRAMEWORK
107+
"Incorrectly indented line ' that:', #1." + Environment.NewLine + "Parameter name: yamlText";
108+
#else
109+
"Incorrectly indented line ' that:', #1. (Parameter 'yamlText')";
110+
#endif
111+
Action act = () => Yaml.Text(BadlyIndentedLines);
112+
113+
act.ShouldThrowExactly<ArgumentException>().WithMessage(expectedMessage);
114+
}
115+
}
116+
}

0 commit comments

Comments
 (0)