Skip to content

Commit ae590e9

Browse files
authored
Merge pull request #782 from hemnstill/mergingparser_with_aliases_try2
MergingParser deserializer can now handle nested NodeSequence with aliases (try2) +semver:fix
2 parents d5a660a + c10f744 commit ae590e9

File tree

5 files changed

+171
-47
lines changed

5 files changed

+171
-47
lines changed

YamlDotNet.Test/Core/EmitterTests.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,7 @@ private IList<ParsingEvent> ParsingEventsOf(string text)
6969
return EnumerationOf(parser).ToList();
7070
}
7171

72-
private IEnumerable<ParsingEvent> EnumerationOf(IParser parser)
73-
{
74-
while (parser.MoveNext())
75-
{
76-
yield return parser.Current;
77-
}
78-
}
72+
7973

8074
[Fact]
8175
public void PlainScalarCanBeFollowedByImplicitDocument()

YamlDotNet.Test/Core/EmitterTestsHelper.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ protected string Emit(IEnumerable<ParsingEvent> events, Func<TextWriter, Emitter
5353
return writer.ToString();
5454
}
5555

56+
protected static IEnumerable<ParsingEvent> EnumerationOf(IParser parser)
57+
{
58+
while (parser.MoveNext())
59+
{
60+
yield return parser.Current;
61+
}
62+
}
63+
5664
protected IEnumerable<ParsingEvent> StreamedDocumentWith(IEnumerable<ParsingEvent> events)
5765
{
5866
return StreamOf(DocumentWith(events.ToArray()));

YamlDotNet.Test/Serialization/DeserializerTest.cs

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
using System;
2323
using System.Collections.Generic;
24-
using System.IO;
2524
using System.Linq;
2625
using FluentAssertions;
2726
using Xunit;
@@ -333,42 +332,6 @@ public void DeserializeWithoutDuplicateKeyChecking_YamlWithDuplicateKeys_DoesNot
333332
act.ShouldNotThrow<YamlException>("Because duplicate key checking is not enabled");
334333
}
335334

336-
[Fact]
337-
public void MergingParserWithMergeObjectWithSequence_ShouldNotThrowException()
338-
{
339-
var yaml = @"
340-
base_level: &base
341-
tenant:
342-
- a1
343-
Level1: &Level1
344-
<<: [*base]
345-
Level2: &Level2
346-
<<: *Level1
347-
";
348-
var mergingParserFailed = new MergingParser(new Parser(new StringReader(yaml)));
349-
var deserializer = new DeserializerBuilder().Build();
350-
Action act = () => deserializer.Deserialize(mergingParserFailed);
351-
act.ShouldNotThrow<Exception>();
352-
}
353-
354-
[Fact]
355-
public void MergingParserWithNestedSequence_ShouldNotThrowException()
356-
{
357-
var yaml = @"
358-
base_level: &base {}
359-
Level1: &Level1
360-
<<: [*base]
361-
Level2: &Level2
362-
<<: [*Level1]
363-
Level3:
364-
<<: *Level2
365-
";
366-
var mergingParserFailed = new MergingParser(new Parser(new StringReader(yaml)));
367-
var deserializer = new DeserializerBuilder().Build();
368-
Action act = () => deserializer.Deserialize(mergingParserFailed);
369-
act.ShouldNotThrow<Exception>();
370-
}
371-
372335
public class Test
373336
{
374337
public string Value { get; set; }
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
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.Collections.Generic;
23+
using System.IO;
24+
using FluentAssertions;
25+
using Xunit;
26+
using YamlDotNet.Core;
27+
using YamlDotNet.Serialization;
28+
using YamlDotNet.Test.Core;
29+
30+
namespace YamlDotNet.Test.Serialization
31+
{
32+
public class MergingParserTests : EmitterTestsHelper
33+
{
34+
[Fact]
35+
public void MergingParserWithMergeObjectWithSequence_EachLevelsShouldEquals()
36+
{
37+
var yaml = @"base_level: &base
38+
tenant:
39+
- a1
40+
- a2
41+
Level1: &Level1
42+
<<: [*base]
43+
Level2: &Level2
44+
<<: *Level1
45+
";
46+
47+
var etalonLevel = @"tenant:
48+
- a1
49+
- a2
50+
".NormalizeNewLines();
51+
52+
var mergingParser = new MergingParser(new Parser(new StringReader(yaml)));
53+
var yamlObject = new DeserializerBuilder().Build().Deserialize<Dictionary<string, object>>(mergingParser);
54+
yamlObject.Should().NotBeNull();
55+
56+
var serializer = new SerializerBuilder().Build();
57+
serializer.Serialize(yamlObject["base_level"]).NormalizeNewLines().Should().Be(etalonLevel);
58+
serializer.Serialize(yamlObject["Level1"]).NormalizeNewLines().Should().Be(etalonLevel);
59+
serializer.Serialize(yamlObject["Level2"]).NormalizeNewLines().Should().Be(etalonLevel);
60+
}
61+
62+
[Fact]
63+
public void MergingParserWithMergeObjectWithSequence_EmittedTextShouldNotContainsDeletedEvents()
64+
{
65+
var yaml = @"base_level: &base
66+
tenant:
67+
- a1
68+
- a2
69+
Level1: &Level1
70+
<<: [*base]
71+
Level2:
72+
<<: *Level1
73+
";
74+
75+
var etalonEmittedText = @"base_level: &base
76+
tenant:
77+
- a1
78+
- a2
79+
Level1: &Level1
80+
tenant:
81+
- a1
82+
- a2
83+
Level2:
84+
tenant:
85+
- a1
86+
- a2
87+
".NormalizeNewLines();
88+
89+
var mergingParser = new MergingParser(new Parser(new StringReader(yaml)));
90+
var events = EnumerationOf(mergingParser);
91+
EmittedTextFrom(events).NormalizeNewLines().Should().Be(etalonEmittedText);
92+
}
93+
94+
[Fact]
95+
public void MergingParserWithMergeObjectWithSequenceAndScalarItems_EmittedTextShouldNotContainsDeletedEvents()
96+
{
97+
var yaml = @"base_level: &base
98+
tenant:
99+
- a1
100+
- a2
101+
Level1: &Level1
102+
<<: [*base]
103+
item1:
104+
Level2:
105+
<<: *Level1
106+
item2:
107+
";
108+
109+
var etalonEmittedText = @"base_level: &base
110+
tenant:
111+
- a1
112+
- a2
113+
Level1: &Level1
114+
tenant:
115+
- a1
116+
- a2
117+
item1: ''
118+
Level2:
119+
tenant:
120+
- a1
121+
- a2
122+
item1: ''
123+
item2: ''
124+
".NormalizeNewLines();
125+
126+
var mergingParser = new MergingParser(new Parser(new StringReader(yaml)));
127+
var events = EnumerationOf(mergingParser);
128+
EmittedTextFrom(events).NormalizeNewLines().Should().Be(etalonEmittedText);
129+
}
130+
131+
[Fact]
132+
public void MergingParserWithNestedSequence_ShouldNotThrowException()
133+
{
134+
var yaml = @"
135+
base_level: &base {}
136+
Level1: &Level1
137+
<<: [*base]
138+
Level2: &Level2
139+
<<: [*Level1]
140+
Level3:
141+
<<: *Level2
142+
";
143+
var etalonMergedYaml = @"base_level: {}
144+
Level1: {}
145+
Level2: {}
146+
Level3: {}
147+
".NormalizeNewLines();
148+
149+
var mergingParserFailed = new MergingParser(new Parser(new StringReader(yaml)));
150+
var yamlObject = new DeserializerBuilder().Build().Deserialize(mergingParserFailed);
151+
152+
new SerializerBuilder().Build().Serialize(yamlObject!).NormalizeNewLines().Should().Be(etalonMergedYaml);
153+
}
154+
}
155+
}

YamlDotNet/Core/MergingParser.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,7 @@ private bool HandleSequence(LinkedListNode<ParsingEvent> node)
140140
var current = node;
141141
while (current != null)
142142
{
143-
if (current.Value is SequenceEnd &&
144-
current.Value.Start.Line >= sequenceStart.Value.Start.Line)
143+
if (current.Value is SequenceEnd)
145144
{
146145
events.MarkDeleted(current);
147146
return true;
@@ -160,7 +159,7 @@ private IEnumerable<ParsingEvent> GetMappingEvents(AnchorName anchor)
160159
var cloner = new ParsingEventCloner();
161160
var nesting = 0;
162161

163-
return events.FromAnchor(anchor)
162+
return events.FromAnchor(anchor).Where(e => !this.events.IsDeleted(e))
164163
.Select(e => e.Value)
165164
.TakeWhile(e => (nesting += e.NestingIncrease) >= 0)
166165
.Select(e => cloner.Clone(e));
@@ -198,6 +197,11 @@ public void MarkDeleted(LinkedListNode<ParsingEvent> node)
198197
deleted.Add(node);
199198
}
200199

200+
public bool IsDeleted(LinkedListNode<ParsingEvent> node)
201+
{
202+
return deleted.Contains(node);
203+
}
204+
201205
public void CleanMarked()
202206
{
203207
foreach (var node in deleted)

0 commit comments

Comments
 (0)