From 854a9c4eb7340097f30d1dd48b5f60bc25a4c911 Mon Sep 17 00:00:00 2001 From: James Dunne Date: Sat, 30 Jun 2012 01:53:58 -0500 Subject: [PATCH] Added new ToDictionaryWithConflictLog to help diagnose ToDictionary bombs. --- OpenRA.FileFormats/Exts.cs | 52 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/OpenRA.FileFormats/Exts.cs b/OpenRA.FileFormats/Exts.cs index 9d4216a5ea..f7e6c538aa 100755 --- a/OpenRA.FileFormats/Exts.cs +++ b/OpenRA.FileFormats/Exts.cs @@ -184,6 +184,58 @@ namespace OpenRA return ts.Concat(moreTs); } + public static Dictionary ToDictionaryWithConflictLog(this IEnumerable source, Func keySelector, string debugName, Func logKey, Func logValue) + { + return ToDictionaryWithConflictLog(source, keySelector, x => x, debugName, logKey, logValue); + } + + public static Dictionary ToDictionaryWithConflictLog(this IEnumerable source, Func keySelector, Func elementSelector, string debugName, Func logKey, Func logValue) + { + // Fall back on ToString() if null functions are provided: + logKey = logKey ?? (s => s.ToString()); + logValue = logValue ?? (s => s.ToString()); + + // Try to build a dictionary and log all duplicates found (if any): + var dupKeys = new Dictionary>(); + var d = new Dictionary(); + foreach (var item in source) + { + TKey key = keySelector(item); + TElement element = elementSelector(item); + + // Check for a key conflict: + if (d.ContainsKey(key)) + { + List dupKeyMessages; + if (!dupKeys.TryGetValue(key, out dupKeyMessages)) + { + // Log the initial conflicting value already inserted: + dupKeyMessages = new List(); + dupKeyMessages.Add(logValue(d[key])); + dupKeys.Add(key, dupKeyMessages); + } + + // Log this conflicting value: + dupKeyMessages.Add(logValue(element)); + continue; + } + + d.Add(key, element); + } + + // If any duplicates were found, log it and throw a descriptive error + if (dupKeys.Count > 0) + { + string badKeysFormatted = String.Join(", ", dupKeys.Select(p => "{0}: [{1}]".F(logKey(p.Key), String.Join(",", p.Value.ToArray()))).ToArray()); + string msg = "{0}, duplicate values found for the following keys: {1}".F(debugName, badKeysFormatted); + Log.Write("debug", msg); + throw new ArgumentException(msg); + } + + // Return the dictionary we built: + return d; + } + public static Color ColorLerp(float t, Color c1, Color c2) { return Color.FromArgb(