File: BoundTree\BoundDecisionDagNode.cs
Web Access
Project: src\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp)
// 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.Diagnostics;
using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CSharp
{
#if DEBUG
    [DebuggerDisplay("{GetDebuggerDisplay(),nq}")]
#endif
    partial class BoundDecisionDagNode
    {
        public override bool Equals(object? other)
        {
            if (this == other)
                return true;
 
            switch (this, other)
            {
                case (BoundEvaluationDecisionDagNode n1, BoundEvaluationDecisionDagNode n2):
                    return n1.Evaluation.Equals(n2.Evaluation) && n1.Next == n2.Next;
                case (BoundTestDecisionDagNode n1, BoundTestDecisionDagNode n2):
                    return n1.Test.Equals(n2.Test) && n1.WhenTrue == n2.WhenTrue && n1.WhenFalse == n2.WhenFalse;
                case (BoundWhenDecisionDagNode n1, BoundWhenDecisionDagNode n2):
                    return n1.WhenExpression == n2.WhenExpression && n1.WhenTrue == n2.WhenTrue && n1.WhenFalse == n2.WhenFalse;
                case (BoundLeafDecisionDagNode n1, BoundLeafDecisionDagNode n2):
                    return n1.Label == n2.Label;
                default:
                    return false;
            }
        }
 
        public override int GetHashCode()
        {
            switch (this)
            {
                case BoundEvaluationDecisionDagNode n:
                    return Hash.Combine(n.Evaluation.GetHashCode(), RuntimeHelpers.GetHashCode(n.Next));
                case BoundTestDecisionDagNode n:
                    return Hash.Combine(n.Test.GetHashCode(), Hash.Combine(RuntimeHelpers.GetHashCode(n.WhenFalse), RuntimeHelpers.GetHashCode(n.WhenTrue)));
                case BoundWhenDecisionDagNode n:
                    return Hash.Combine(RuntimeHelpers.GetHashCode(n.WhenExpression), Hash.Combine(RuntimeHelpers.GetHashCode(n.WhenFalse), RuntimeHelpers.GetHashCode(n.WhenTrue)));
                case BoundLeafDecisionDagNode n:
                    return RuntimeHelpers.GetHashCode(n.Label);
                default:
                    throw ExceptionUtilities.UnexpectedValue(this);
            }
        }
 
#if DEBUG
        private int _id = -1;
 
        public int Id
        {
            get
            {
                return _id;
            }
            internal set
            {
                Debug.Assert(value >= 0, "Id must be non-negative but was set to " + value);
                Debug.Assert(_id == -1, $"Id was set to {_id} and set again to {value}");
                _id = value;
            }
        }
 
        internal new string GetDebuggerDisplay()
        {
            var pooledBuilder = PooledStringBuilder.GetInstance();
            var builder = pooledBuilder.Builder;
            builder.Append($"[{this.Id}]: ");
            switch (this)
            {
                case BoundTestDecisionDagNode node:
                    builder.Append($"{node.Test.GetDebuggerDisplay()} ");
                    builder.Append(node.WhenTrue != null
                        ? $"? [{node.WhenTrue.Id}] "
                        : "? <unreachable> ");
 
                    builder.Append(node.WhenFalse != null
                        ? $": [{node.WhenFalse.Id}]"
                        : ": <unreachable>");
                    break;
                case BoundEvaluationDecisionDagNode node:
                    builder.Append($"{node.Evaluation.GetDebuggerDisplay()}; ");
                    builder.Append(node.Next != null
                        ? $"[{node.Next.Id}]"
                        : "<unreachable>");
                    break;
                case BoundWhenDecisionDagNode node:
                    builder.Append("when ");
                    builder.Append(node.WhenExpression is { } when
                        ? $"({when.Syntax}) "
                        : "<true> ");
 
                    builder.Append(node.WhenTrue != null
                        ? $"? [{node.WhenTrue.Id}] "
                        : "? <unreachable> ");
 
                    builder.Append(node.WhenFalse != null
                        ? $": [{node.WhenFalse.Id}]"
                        : ": <unreachable>");
 
                    break;
                case BoundLeafDecisionDagNode node:
                    builder.Append(node.Label is GeneratedLabelSymbol generated
                        ? $"leaf {generated.NameNoSequence} `{node.Syntax}`"
                        : $"leaf `{node.Label.Name}`");
                    break;
                default:
                    builder.Append(base.GetDebuggerDisplay());
                    break;
            }
 
            return pooledBuilder.ToStringAndFree();
        }
#endif
    }
}