| File: SwitchConstantValueHelper.cs | Web Access |
| Project: src\roslyn\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Generic; using System.Diagnostics; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis { /// <summary> /// Contains helper methods for switch statement label constants /// </summary> internal static class SwitchConstantValueHelper { public static bool IsValidSwitchCaseLabelConstant(ConstantValue constant) { switch (constant.Discriminator) { case ConstantValueTypeDiscriminator.Null: case ConstantValueTypeDiscriminator.SByte: case ConstantValueTypeDiscriminator.Byte: case ConstantValueTypeDiscriminator.Int16: case ConstantValueTypeDiscriminator.UInt16: case ConstantValueTypeDiscriminator.Int32: case ConstantValueTypeDiscriminator.UInt32: case ConstantValueTypeDiscriminator.Int64: case ConstantValueTypeDiscriminator.UInt64: case ConstantValueTypeDiscriminator.Char: case ConstantValueTypeDiscriminator.Boolean: case ConstantValueTypeDiscriminator.String: return true; default: return false; } } /// <summary> /// Method used to compare ConstantValues for switch statement case labels /// </summary> /// <param name="first"></param> /// <param name="second"></param> /// <returns>A value that indicates the relative order of the objects being compared. The return value has these meanings: /// Less than zero: first instance precedes second in the sort order. /// Zero: first instance occurs in the same position in the sort order as second. /// Greater than zero: first instance follows second in the sort order. /// </returns> public static int CompareSwitchCaseLabelConstants(ConstantValue first, ConstantValue second) { RoslynDebug.Assert(first != null); RoslynDebug.Assert(second != null); RoslynDebug.Assert(IsValidSwitchCaseLabelConstant(first)); RoslynDebug.Assert(IsValidSwitchCaseLabelConstant(second)); if (first.IsNull) { // first instance has ConstantValue Null. // If second instance ConstantValue is Null, both instances are equal. // Else, second instance is greater. return second.IsNull ? 0 : -1; } else if (second.IsNull) { // second instance has ConstantValue Null and first instance has non-null ConstantValue. // first instance is greater. return 1; } switch (first.Discriminator) { case ConstantValueTypeDiscriminator.SByte: case ConstantValueTypeDiscriminator.Int16: case ConstantValueTypeDiscriminator.Int32: case ConstantValueTypeDiscriminator.Int64: return first.Int64Value.CompareTo(second.Int64Value); case ConstantValueTypeDiscriminator.Boolean: case ConstantValueTypeDiscriminator.Byte: case ConstantValueTypeDiscriminator.UInt16: case ConstantValueTypeDiscriminator.UInt32: case ConstantValueTypeDiscriminator.UInt64: case ConstantValueTypeDiscriminator.Char: return first.UInt64Value.CompareTo(second.UInt64Value); case ConstantValueTypeDiscriminator.String: Debug.Assert(second.IsString); return string.CompareOrdinal(first.StringValue, second.StringValue); default: throw ExceptionUtilities.UnexpectedValue(first.Discriminator); } } public class SwitchLabelsComparer : EqualityComparer<object> { public override bool Equals(object? first, object? second) { RoslynDebug.Assert(first != null && second != null); var firstConstant = first as ConstantValue; if (firstConstant != null) { var secondConstant = second as ConstantValue; if (secondConstant != null) { if (!IsValidSwitchCaseLabelConstant(firstConstant) || !IsValidSwitchCaseLabelConstant(secondConstant)) { // We don't care about invalid case labels with duplicate value as // we will generate diagnostics for invalid case label. return firstConstant.Equals(secondConstant); } return CompareSwitchCaseLabelConstants(firstConstant, secondConstant) == 0; } } var firstString = first as string; if (firstString != null) { return string.Equals(firstString, second as string, System.StringComparison.Ordinal); } return first.Equals(second); } public override int GetHashCode(object obj) { var constant = obj as ConstantValue; if (constant != null) { switch (constant.Discriminator) { case ConstantValueTypeDiscriminator.SByte: case ConstantValueTypeDiscriminator.Int16: case ConstantValueTypeDiscriminator.Int32: case ConstantValueTypeDiscriminator.Int64: return constant.Int64Value.GetHashCode(); case ConstantValueTypeDiscriminator.Boolean: case ConstantValueTypeDiscriminator.Byte: case ConstantValueTypeDiscriminator.UInt16: case ConstantValueTypeDiscriminator.UInt32: case ConstantValueTypeDiscriminator.UInt64: case ConstantValueTypeDiscriminator.Char: return constant.UInt64Value.GetHashCode(); case ConstantValueTypeDiscriminator.String: return constant.RopeValue!.GetHashCode(); } } return obj.GetHashCode(); } } } }