File: Protocol\SymbolInformation.cs
Web Access
Project: src\src\LanguageServer\Protocol\Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj (Microsoft.CodeAnalysis.LanguageServer.Protocol)
// 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.
 
namespace Roslyn.LanguageServer.Protocol
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text.Json.Serialization;
    using Roslyn.Utilities;
 
    /// <summary>
    /// Class representing information about programming constructs like variables, classes, interfaces, etc.
    /// <para>
    /// See the <see href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#symbolInformation">Language Server Protocol specification</see> for additional information.
    /// </para>
    /// </summary>
    internal class SymbolInformation : IEquatable<SymbolInformation>
    {
 
        // Code has to reference SymbolInformation in a SumType even if it's not using the class itself.
        // This means that if we deprecate the type itself, referencing code would have to suppress
        // deprecation  warnings even if they are only using non-deprecated types. We work around
        // by deprecating the members instead of the type itself.
        const string DeprecationMessage = "The SymbolInformation class is deprecated. Use DocumentSymbol or WorkspaceSymbol instead.";
 
        /// <summary>
        /// Gets or sets the name of this symbol.
        /// </summary>
        [JsonPropertyName("name")]
        [Obsolete(DeprecationMessage)]
        public string Name
        {
            get;
            set;
        }
 
        /// <summary>
        /// Gets or sets the <see cref="SymbolKind"/> of this symbol.
        /// </summary>
        [JsonPropertyName("kind")]
        [Obsolete(DeprecationMessage)]
        public SymbolKind Kind
        {
            get;
            set;
        }
 
        /// <summary>
        /// Tags for this document symbol.
        /// </summary>
        /// <remarks>Since 3.16</remarks>
        [JsonPropertyName("tags")]
        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
        [Obsolete(DeprecationMessage)]
        public SymbolTag[]? Tags { get; init; }
 
        /// <summary>
        /// Indicates whether this symbol is deprecated.
        /// </summary>
        [JsonPropertyName("deprecated")]
        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
        [Obsolete("Use the Tags property instead")]
        public bool Deprecated { get; init; }
 
        /// <summary>
        /// The location of this symbol, used by a tool to reveal the location in the editor.
        /// <para>
        /// If the symbol is selected in the tool the range's start information is used to
        /// position the cursor. So the range usually spans more then the actual symbol's
        /// name and does normally include things like visibility modifiers.
        /// </para>
        /// <para>
        /// The range doesn't have to denote a node range in the sense of an abstract
        /// syntax tree. It can therefore not be used to re-construct a hierarchy of
        /// the symbols.
        /// </para>
        /// </summary>
        [JsonPropertyName("location")]
        [Obsolete(DeprecationMessage)]
        public Location Location
        {
            get;
            set;
        }
 
        /// <summary>
        /// <para>
        /// The name of the symbol containing this symbol.
        /// </para>
        /// This information is for user interface purposes (e.g. to render a qualifier in
        /// the user interface if necessary). It can't be used to re-infer a hierarchy for
        /// the document symbols.
        /// </summary>
        [JsonPropertyName("containerName")]
        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
        [Obsolete(DeprecationMessage)]
        public string? ContainerName
        {
            get;
            set;
        }
 
        /// <inheritdoc/>
        public override bool Equals(object obj)
        {
            return this.Equals(obj as SymbolInformation);
        }
 
        /// <inheritdoc/>
        public bool Equals(SymbolInformation? other)
        {
#pragma warning disable CS0618 // Type or member is obsolete
            return other != null
                && this.Name == other.Name
                && this.Kind == other.Kind
                && (this.Tags == null
                        ? other.Tags == null
                        : (this.Tags.Equals(other.Tags) || this.Tags.SequenceEqual(other.Tags)))
                && this.Deprecated == other.Deprecated
                && EqualityComparer<Location>.Default.Equals(this.Location, other.Location)
                && this.ContainerName == other.ContainerName;
#pragma warning restore CS0618
        }
 
        /// <inheritdoc/>
        public override int GetHashCode() =>
#pragma warning disable CS0618 // Type or member is obsolete
#if NET
            HashCode.Combine(Name, Kind, Hash.CombineValues(Tags), Deprecated, Location, ContainerName);
#else
            Hash.Combine(Name,
            Hash.Combine((int)Kind,
            Hash.Combine(Hash.CombineValues(Tags),
            Hash.Combine(Deprecated,
            Hash.Combine(ContainerName, Location?.GetHashCode() ?? 0)))));
#endif
#pragma warning restore CS0618
    }
}