Skip to content

Commit

Permalink
Merge pull request #887 from dougbu/dougbu/blank.lines.886
Browse files Browse the repository at this point in the history
Handle blank lines in `Yaml.Text()`
  • Loading branch information
EdwardCooke committed Jan 23, 2024
2 parents 7daf14c + c04446e commit fa65881
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 18 deletions.
28 changes: 14 additions & 14 deletions YamlDotNet.Test/Serialization/SerializationTests.cs
Expand Up @@ -253,7 +253,7 @@ public void DeserializeWithGapsBetweenKeys()
{
var yamlReader = new StringReader(@"Text: >
Some Text.
Value: foo");
var result = Deserializer.Deserialize(yamlReader);

Expand Down Expand Up @@ -1203,10 +1203,10 @@ public void BackreferencesAreMergedWithMappings()
public void MergingDoesNotProduceDuplicateAnchors()
{
var parser = new MergingParser(Yaml.ParserForText(@"
anchor: &default
anchor: &default
key1: &myValue value1
key2: value2
alias:
alias:
<<: *default
key2: Overriding key2
key3: value3
Expand Down Expand Up @@ -1234,24 +1234,24 @@ public void ExampleFromSpecificationIsHandledCorrectly()
- &LEFT { x: 0, y: 2 }
- &BIG { r: 10 }
- &SMALL { r: 1 }
# All the following maps are equal:
results:
- # Explicit keys
x: 1
y: 2
r: 10
label: center/big
- # Merge one map
<< : *CENTER
r: 10
label: center/big
- # Merge multiple maps
<< : [ *CENTER, *BIG ]
label: center/big
- # Override
<< : [ *BIG, *LEFT, *SMALL ]
x: 1
Expand Down Expand Up @@ -1287,10 +1287,10 @@ public void MergeNestedReferenceCorrectly()
derived1:
<<: *level1
key: D1
derived2:
derived2:
<<: *level2
key: D2
derived3:
derived3:
<<: [ *level1, *level2 ]
key: D3
"));
Expand Down Expand Up @@ -2169,29 +2169,29 @@ public void ShouldIndentSequences()
[Fact]
public void ExampleFromSpecificationIsHandledCorrectlyWithLateDefine()
{
var parser = new MergingParser(Yaml.ParserForText(@"
var parser = new MergingParser(Yaml.ParserForText(@"
# All the following maps are equal:
results:
- # Explicit keys
x: 1
y: 2
r: 10
label: center/big
- # Merge one map
<< : *CENTER
r: 10
label: center/big
- # Merge multiple maps
<< : [ *CENTER, *BIG ]
label: center/big
- # Override
<< : [ *BIG, *LEFT, *SMALL ]
x: 1
label: center/big
obj:
- &CENTER { x: 1, y: 2 }
- &LEFT { x: 0, y: 2 }
Expand Down
15 changes: 11 additions & 4 deletions YamlDotNet.Test/Yaml.cs
Expand Up @@ -90,11 +90,11 @@ public static string Text(string yamlText)
{
var lines = yamlText
.Split('\n')
.Select(l => l.TrimEnd('\r', '\n'))
.SkipWhile(l => l.Trim(' ', '\t').Length == 0)
.Select(l => l.TrimEnd())
.SkipWhile(l => l.Length == 0)
.ToList();

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

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

Expand Down
116 changes: 116 additions & 0 deletions YamlDotNet.Test/YamlTests.cs
@@ -0,0 +1,116 @@
// This file is part of YamlDotNet - A .NET library for YAML.
// Copyright (c) Antoine Aubry and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using System;
using FluentAssertions;
using Xunit;

namespace YamlDotNet.Test
{
public class YamlTests
{
private const string SingleLine = "object:";
private const string LeadingBlankLines = @"
object:";
private const string LeadingBlankLinesWithWhitespace = @"
object:";
private const string TrailingBlankLines = @"object:
";
private const string TrailingBlankLinesWithWhitespace = @"object:
";

private const string Lines = @"this:
that:
theOtherThing:";
private const string IndentedLines = @" this:
that:
theOtherThing:";

private const string NestedLines = @"Map1:
Map2:
- entry 1
- entry 2
- entry 3";
private const string IndentedNestedLines = @" Map1:
Map2:
- entry 1
- entry 2
- entry 3";

private const string SomeBlankLines = @"this:
that:
theOtherThing:";
private const string SomeBlankLinesWithWhitespace = @"this:
that:
theOtherThing:";

[Theory]
[InlineData(SingleLine, SingleLine)]
[InlineData(LeadingBlankLines, SingleLine)]
[InlineData(LeadingBlankLinesWithWhitespace, SingleLine)]
[InlineData(TrailingBlankLines, SingleLine)]
[InlineData(TrailingBlankLinesWithWhitespace, SingleLine)]
[InlineData(Lines, Lines)]
[InlineData(IndentedLines, Lines)]
[InlineData(NestedLines, NestedLines)]
[InlineData(IndentedNestedLines, NestedLines)]
[InlineData(SomeBlankLines, SomeBlankLines)]
[InlineData(SomeBlankLinesWithWhitespace, SomeBlankLines)]
public void TextProducesExpectedOutput(string text, string expectedText)
{
expectedText = expectedText.NormalizeNewLines();
var result = Yaml.Text(text);

result.NormalizeNewLines().Should().Be(expectedText);
}

[Fact]
public void TextThrowsArgumentOutOfRangeExceptionForInsuffientIndentation()
{
const string BadlyIndentedLines = @" this:
that:
theOtherThing:";
var expectedMessage =
#if NETFRAMEWORK
"Incorrectly indented line ' that:', #1." + Environment.NewLine + "Parameter name: yamlText";
#else
"Incorrectly indented line ' that:', #1. (Parameter 'yamlText')";
#endif
Action act = () => Yaml.Text(BadlyIndentedLines);

act.ShouldThrowExactly<ArgumentException>().WithMessage(expectedMessage);
}
}
}

0 comments on commit fa65881

Please sign in to comment.