Rewrite yaml merging block removal.

Fixes #2922, #6818.
This commit is contained in:
Paul Chote
2015-04-21 19:30:43 +12:00
parent b4fa704fbd
commit 0a43b3da72
2 changed files with 33 additions and 26 deletions

View File

@@ -37,7 +37,6 @@ namespace OpenRA
Name = name; Name = name;
foreach (var t in mergedNode) foreach (var t in mergedNode)
if (t.Key != "Inherits" && !t.Key.StartsWith("-"))
Traits.Add(LoadTraitInfo(t.Key.Split('@')[0], t.Value)); Traits.Add(LoadTraitInfo(t.Key.Split('@')[0], t.Value));
} }
catch (YamlException e) catch (YamlException e)
@@ -69,8 +68,7 @@ namespace OpenRA
{ {
var result = MiniYaml.MergeStrict(node, MergeWithParent(parent, allUnits)); var result = MiniYaml.MergeStrict(node, MergeWithParent(parent, allUnits));
// strip the '-' result.Nodes.RemoveAll(a => a.Key == "Inherits");
result.Nodes.RemoveAll(a => a.Key.StartsWith("-"));
return result; return result;
} }

53
OpenRA.Game/MiniYaml.cs Executable file → Normal file
View File

@@ -254,17 +254,17 @@ namespace OpenRA
return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries), fileName); return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries), fileName);
} }
public static List<MiniYamlNode> MergeLiberal(List<MiniYamlNode> a, List<MiniYamlNode> b) public static List<MiniYamlNode> MergeStrict(List<MiniYamlNode> a, List<MiniYamlNode> b)
{ {
return Merge(a, b, false); return Merge(a, b, false);
} }
public static List<MiniYamlNode> MergeStrict(List<MiniYamlNode> a, List<MiniYamlNode> b) public static List<MiniYamlNode> MergeLiberal(List<MiniYamlNode> a, List<MiniYamlNode> b)
{ {
return Merge(a, b, true); return Merge(a, b, true);
} }
static List<MiniYamlNode> Merge(List<MiniYamlNode> a, List<MiniYamlNode> b, bool throwErrors) static List<MiniYamlNode> Merge(List<MiniYamlNode> a, List<MiniYamlNode> b, bool allowUnresolvedRemoves = false)
{ {
if (a.Count == 0) if (a.Count == 0)
return b; return b;
@@ -275,10 +275,11 @@ namespace OpenRA
var dictA = a.ToDictionaryWithConflictLog(x => x.Key, "MiniYaml.Merge", null, x => "{0} (at {1})".F(x.Key, x.Location)); var dictA = a.ToDictionaryWithConflictLog(x => x.Key, "MiniYaml.Merge", null, x => "{0} (at {1})".F(x.Key, x.Location));
var dictB = b.ToDictionaryWithConflictLog(x => x.Key, "MiniYaml.Merge", null, x => "{0} (at {1})".F(x.Key, x.Location)); var dictB = b.ToDictionaryWithConflictLog(x => x.Key, "MiniYaml.Merge", null, x => "{0} (at {1})".F(x.Key, x.Location));
var keys = dictA.Keys.Union(dictB.Keys).ToList(); var allKeys = dictA.Keys.Union(dictB.Keys);
var noInherit = keys.Where(x => x.Length > 0 && x[0] == '-') var keys = allKeys.Where(x => x.Length == 0 || x[0] != '-').ToList();
.ToDictionary(x => x.Substring(1), x => false); var removeKeys = allKeys.Where(x => x.Length > 0 && x[0] == '-')
.Select(k => k.Substring(1)).ToHashSet();
foreach (var key in keys) foreach (var key in keys)
{ {
@@ -286,47 +287,55 @@ namespace OpenRA
dictA.TryGetValue(key, out aa); dictA.TryGetValue(key, out aa);
dictB.TryGetValue(key, out bb); dictB.TryGetValue(key, out bb);
if (noInherit.ContainsKey(key)) if (removeKeys.Contains(key))
{ removeKeys.Remove(key);
if (!throwErrors)
if (aa != null)
ret.Add(aa);
noInherit[key] = true;
}
else else
{ {
var loc = aa == null ? default(MiniYamlNode.SourceLocation) : aa.Location; var loc = aa == null ? default(MiniYamlNode.SourceLocation) : aa.Location;
var merged = (aa == null || bb == null) ? aa ?? bb : new MiniYamlNode(key, Merge(aa.Value, bb.Value, throwErrors), loc); var merged = (aa == null || bb == null) ? aa ?? bb : new MiniYamlNode(key, Merge(aa.Value, bb.Value, allowUnresolvedRemoves), loc);
ret.Add(merged); ret.Add(merged);
} }
} }
if (throwErrors && noInherit.ContainsValue(false)) if (removeKeys.Any())
throw new YamlException("Bogus yaml removals: {0}".F( {
noInherit.Where(x => !x.Value).JoinWith(", "))); if (allowUnresolvedRemoves)
{
// Add the removal nodes back for the next pass to deal with
foreach (var k in removeKeys)
{
var key = "-" + k;
MiniYamlNode rem;
if (!dictA.TryGetValue(key, out rem))
rem = dictB[key];
ret.Add(rem);
}
}
else
throw new YamlException("Bogus yaml removals: {0}".F(removeKeys.JoinWith(", ")));
}
return ret; return ret;
} }
public static MiniYaml MergeLiberal(MiniYaml a, MiniYaml b) public static MiniYaml MergeLiberal(MiniYaml a, MiniYaml b)
{ {
return Merge(a, b, false); return Merge(a, b, true);
} }
public static MiniYaml MergeStrict(MiniYaml a, MiniYaml b) public static MiniYaml MergeStrict(MiniYaml a, MiniYaml b)
{ {
return Merge(a, b, true); return Merge(a, b, false);
} }
static MiniYaml Merge(MiniYaml a, MiniYaml b, bool throwErrors) static MiniYaml Merge(MiniYaml a, MiniYaml b, bool allowUnresolvedRemoves)
{ {
if (a == null) if (a == null)
return b; return b;
if (b == null) if (b == null)
return a; return a;
return new MiniYaml(a.Value ?? b.Value, Merge(a.Nodes, b.Nodes, throwErrors)); return new MiniYaml(a.Value ?? b.Value, Merge(a.Nodes, b.Nodes, allowUnresolvedRemoves));
} }
public IEnumerable<string> ToLines(string name) public IEnumerable<string> ToLines(string name)