| File: CodeGen\LocalDebugId.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; using System.Diagnostics; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CodeGen { /// <summary> /// Id that associates an emitted user-defined or long-lived synthesized local variable /// with a syntax node that defined it. If a syntax node defines multiple variables it /// provides information necessary to identify which one of these variables is it. /// </summary> internal readonly struct LocalDebugId : IEquatable<LocalDebugId> { /// <summary> /// We calculate a "syntax offset" for each user-defined and long-lived synthesized variable. /// Every such variable symbol has to be associated with a syntax node (its declarator). /// In usual cases this is the textual distance of the declarator from the start of the method body. /// It gets a bit complicated when the containing method body is not contiguous (constructors). /// If the variable is in the body of the constructor the definition of syntax offset is the same. /// If the variable is defined in a constructor initializer or in a member initializer /// (this is only possible when declaration expressions or closures in primary constructors are involved) /// then the distance is a negative sum of the widths of all the initializers that succeed the declarator /// of the variable in the emitted constructor body plus the relative offset of the declarator from /// the start of the containing initializer. /// </summary> public readonly int SyntaxOffset; /// <summary> /// If a single node is a declarator for multiple variables of the same synthesized kind (it can only happen for synthesized variables) /// we calculate additional number "ordinal" for such variable. We assign the ordinals to the synthesized variables with the same kind /// and syntax offset in the order as they appear in the lowered bound tree. It is important that a valid EnC edit can't change /// the ordinal of a synthesized variable. If it could it would need to be assigned a different kind or associated with a different declarator node. /// </summary> public readonly int Ordinal; public static readonly LocalDebugId None = new LocalDebugId(isNone: true); private LocalDebugId(bool isNone) { Debug.Assert(isNone); this.SyntaxOffset = -1; this.Ordinal = -1; } public LocalDebugId(int syntaxOffset, int ordinal = 0) { Debug.Assert(ordinal >= 0); this.SyntaxOffset = syntaxOffset; this.Ordinal = ordinal; } public bool IsNone { get { return Ordinal == -1; } } public bool Equals(LocalDebugId other) { return SyntaxOffset == other.SyntaxOffset && Ordinal == other.Ordinal; } public override int GetHashCode() { return Hash.Combine(SyntaxOffset, Ordinal); } public override bool Equals(object? obj) { return obj is LocalDebugId && Equals((LocalDebugId)obj); } public override string ToString() { return SyntaxOffset + ":" + Ordinal; } } }