Extend MiniYaml parser with new features:

- Add support for escaping '#' inside values
- Add support for escaping leading and trailing whitespace

And when discardCommentsAndWhitespace is set to false:
- Add proper support for comments
- Persist empty lines

Whitespace and comment support requires an explicit opt-in because
they produce MiniYamlNodes with null keys.  Supporting these through
the entire game engine would require changing all yaml enumerations
to explicitly check and account for these keys with no benefit.

Comments and whitespace are now treated as real nodes during parsing,
which means that the yaml parser will throw errors if they have
incorrect indentation, even if these nodes will be discarded.
This commit is contained in:
Paul Chote
2018-05-07 17:49:21 +00:00
committed by reaperrr
parent 7a41b3aa89
commit df31690332
5 changed files with 222 additions and 98 deletions

View File

@@ -194,5 +194,82 @@ Test:
Assert.That(mergeNode.Value, Is.EqualTo("override"), "Merge node has incorrect value.");
Assert.That(mergeNode.Nodes[0].Value.Value, Is.EqualTo("override"), "Merge node Child value should be 'override', but is not");
}
[TestCase(TestName = "Comments are correctly separated from values")]
public void TestEscapedHashInValues()
{
var trailingWhitespace = @"key: value # comment";
Assert.AreEqual("value", MiniYaml.FromString(trailingWhitespace, "trailingWhitespace")[0].Value.Value);
var noWhitespace = @"key:value# comment";
Assert.AreEqual("value", MiniYaml.FromString(noWhitespace, "noWhitespace")[0].Value.Value);
var escapedHashInValue = @"key: before \# after # comment";
Assert.AreEqual("before # after", MiniYaml.FromString(escapedHashInValue, "escapedHashInValue")[0].Value.Value);
var emptyValue = @"key:# comment";
Assert.AreEqual(null, MiniYaml.FromString(emptyValue, "emptyValue")[0].Value.Value);
}
[TestCase(TestName = "Leading and trailing whitespace can be guarded using a backslash")]
public void TestGuardedWhitespace()
{
var testYaml = @"key: \ test value \ ";
var nodes = MiniYaml.FromString(testYaml, "testYaml");
Assert.AreEqual(" test value ", nodes[0].Value.Value);
}
[TestCase(TestName = "Comments should count toward line numbers")]
public void CommentsShouldCountTowardLineNumbers()
{
var yaml = @"
TestA:
Nothing:
# Comment
TestB:
Nothing:
";
var resultDiscard = MiniYaml.FromString(yaml).First(n => n.Key == "TestB");
Assert.That(resultDiscard.Location.Line, Is.EqualTo(6), "Node TestB should report its location as line 6, but is not (discarding comments)");
var resultKeep = MiniYaml.FromString(yaml, discardCommentsAndWhitespace: false).First(n => n.Key == "TestB");
Assert.That(resultDiscard.Location.Line, Is.EqualTo(6), "Node TestB should report its location as line 6, but is not (parsing comments)");
}
[TestCase(TestName = "Comments should survive a round trip intact")]
public void CommentsSurviveRoundTrip()
{
var yaml = @"
# Top level comment node
Parent: # comment without value
# Indented comment node
First: value containing a \# character
Second: value # node with inline comment
";
var result = MiniYaml.FromString(yaml, discardCommentsAndWhitespace: false).WriteToString();
Assert.AreEqual(yaml, result);
}
[TestCase(TestName = "Comments should be be removed when discardCommentsAndWhitespace is false")]
public void CommentsShouldntSurviveRoundTrip()
{
var yaml = @"
# Top level comment node
Parent: # comment without value
# Indented comment node
First: value containing a \# character
Second: value # node with inline comment
";
var strippedYaml = @"Parent:
First: value containing a \# character
Second: value";
var result = MiniYaml.FromString(yaml).WriteToString();
Assert.AreEqual(strippedYaml, result);
}
}
}