diff --git a/src/Compilers/Core/Portable/Diagnostic/Diagnostic_SimpleDiagnostic.cs b/src/Compilers/Core/Portable/Diagnostic/Diagnostic_SimpleDiagnostic.cs index 4d36f6c3db7c7..e5c370a9c0ff1 100644 --- a/src/Compilers/Core/Portable/Diagnostic/Diagnostic_SimpleDiagnostic.cs +++ b/src/Compilers/Core/Portable/Diagnostic/Diagnostic_SimpleDiagnostic.cs @@ -34,13 +34,18 @@ private SimpleDiagnostic( if ((warningLevel == 0 && severity != DiagnosticSeverity.Error) || (warningLevel != 0 && severity == DiagnosticSeverity.Error)) { - throw new ArgumentException("warningLevel"); + throw new ArgumentException(nameof(warningLevel)); + } + + if(descriptor == null) + { + throw new ArgumentNullException(nameof(descriptor)); } _descriptor = descriptor; _severity = severity; _warningLevel = warningLevel; - _location = location; + _location = location ?? Location.None; _additionalLocations = additionalLocations == null ? SpecializedCollections.EmptyReadOnlyList() : additionalLocations.ToImmutableArray(); _messageArgs = messageArgs ?? SpecializedCollections.EmptyArray(); } @@ -131,10 +136,9 @@ public override bool Equals(object obj) public override int GetHashCode() { return Hash.Combine(_descriptor, - Hash.Combine(_messageArgs.GetHashCode(), - Hash.Combine(_location.GetHashCode(), - Hash.Combine(_severity.GetHashCode(), _warningLevel) - ))); + Hash.CombineValues(_messageArgs, + Hash.Combine(_warningLevel, + Hash.Combine(_location, (int)_severity)))); } internal override Diagnostic WithLocation(Location location) diff --git a/src/Compilers/Core/Portable/InternalUtilities/Hash.cs b/src/Compilers/Core/Portable/InternalUtilities/Hash.cs index 4dfeff33829be..1bb82411f4323 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/Hash.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/Hash.cs @@ -66,6 +66,30 @@ internal static int CombineValues(IEnumerable values, int maxItemsToHash = return hashCode; } + internal static int CombineValues(T[] values, int maxItemsToHash = int.MaxValue) + { + if (values == null) + { + return 0; + } + + var maxSize = Math.Min(maxItemsToHash, values.Length); + var hashCode = 0; + + for (int i = 0; i < maxSize; i++) + { + T value = values[i]; + + // Should end up with a constrained virtual call to object.GetHashCode (i.e. avoid boxing where possible). + if (value != null) + { + hashCode = Hash.Combine(value.GetHashCode(), hashCode); + } + } + + return hashCode; + } + internal static int CombineValues(ImmutableArray values, int maxItemsToHash = int.MaxValue) { if (values.IsDefaultOrEmpty)