File: src\roslyn\src\Workspaces\SharedUtilitiesAndExtensions\Workspace\Core\CodeGeneration\Symbols\CodeGenerationSymbol.cs
Web Access
Project: src\roslyn\src\RoslynAnalyzers\Tools\GenerateDocumentationAndConfigFiles\GenerateDocumentationAndConfigFiles.csproj (GenerateDocumentationAndConfigFiles)
// 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.

#nullable disable

using System;
using System.Collections.Immutable;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Threading;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Shared.Extensions;

namespace Microsoft.CodeAnalysis.CodeGeneration;

internal abstract class CodeGenerationSymbol : ISymbol
{
    protected static ConditionalWeakTable<CodeGenerationSymbol, SyntaxAnnotation[]> annotationsTable = new();

    private readonly ImmutableArray<AttributeData> _attributes;
    protected readonly string _documentationCommentXml;

    public Accessibility DeclaredAccessibility { get; }
    protected internal DeclarationModifiers Modifiers { get; }
    public string Name { get; }
    public INamedTypeSymbol ContainingType { get; protected set; }

    protected CodeGenerationSymbol(
        IAssemblySymbol containingAssembly,
        INamedTypeSymbol containingType,
        ImmutableArray<AttributeData> attributes,
        Accessibility declaredAccessibility,
        DeclarationModifiers modifiers,
        string name,
        string documentationCommentXml = null)
    {
        this.ContainingAssembly = containingAssembly;
        this.ContainingType = containingType;
        _attributes = attributes.NullToEmpty();
        this.DeclaredAccessibility = declaredAccessibility;
        this.Modifiers = modifiers;
        this.Name = name;
        _documentationCommentXml = documentationCommentXml;
    }

    protected abstract CodeGenerationSymbol Clone();

    internal SyntaxAnnotation[] GetAnnotations()
    {
        annotationsTable.TryGetValue(this, out var annotations);
        return annotations ?? [];
    }

    internal CodeGenerationSymbol WithAdditionalAnnotations(params SyntaxAnnotation[] annotations)
    {
        return annotations.IsNullOrEmpty()
            ? this
            : AddAnnotationsTo(this, this.Clone(), annotations);
    }

    private static CodeGenerationSymbol AddAnnotationsTo(
        CodeGenerationSymbol originalDefinition, CodeGenerationSymbol newDefinition, SyntaxAnnotation[] annotations)
    {
        annotationsTable.TryGetValue(originalDefinition, out var originalAnnotations);

        annotations = SyntaxAnnotationExtensions.CombineAnnotations(originalAnnotations, annotations);
        annotationsTable.Add(newDefinition, annotations);

        return newDefinition;
    }

    public abstract SymbolKind Kind { get; }

    public string Language => "Code Generation Agnostic Language";

    public virtual ISymbol ContainingSymbol => null;

    public IAssemblySymbol ContainingAssembly { get; }

    public static IMethodSymbol ContainingMethod => null;

    public IModuleSymbol ContainingModule => null;

    public INamespaceSymbol ContainingNamespace => null;

    public bool IsDefinition => true;

    public bool IsStatic
    {
        get
        {
            return this.Modifiers.IsStatic;
        }
    }

    public bool IsVirtual
    {
        get
        {
            return this.Modifiers.IsVirtual;
        }
    }

    public bool IsOverride
    {
        get
        {
            return this.Modifiers.IsOverride;
        }
    }

    public bool IsAbstract
    {
        get
        {
            return this.Modifiers.IsAbstract;
        }
    }

    public bool IsSealed
    {
        get
        {
            return this.Modifiers.IsSealed;
        }
    }

    public bool IsExtern => false;

    public bool IsImplicitlyDeclared => false;

    public bool CanBeReferencedByName => true;

    public ImmutableArray<Location> Locations
    {
        get
        {
            return [];
        }
    }

    public static ImmutableArray<SyntaxNode> DeclaringSyntaxNodes
    {
        get
        {
            return [];
        }
    }

    public ImmutableArray<SyntaxReference> DeclaringSyntaxReferences
    {
        get
        {
            return [];
        }
    }

    public ImmutableArray<AttributeData> GetAttributes()
        => _attributes;

    public ImmutableArray<AttributeData> GetAttributes(INamedTypeSymbol attributeType)
        => GetAttributes().WhereAsArray(a => a.AttributeClass.Equals(attributeType));

    public ImmutableArray<AttributeData> GetAttributes(IMethodSymbol attributeConstructor)
        => GetAttributes().WhereAsArray(a => a.AttributeConstructor.Equals(attributeConstructor));

    public ISymbol OriginalDefinition
    {
        get
        {
            return this;
        }
    }

    public abstract void Accept(SymbolVisitor visitor);

    public abstract TResult Accept<TResult>(SymbolVisitor<TResult> visitor);

    public abstract TResult Accept<TArgument, TResult>(SymbolVisitor<TArgument, TResult> visitor, TArgument argument);

    public string GetDocumentationCommentId()
        => null;

    public string GetDocumentationCommentXml(
        CultureInfo preferredCulture,
        bool expandIncludes,
        CancellationToken cancellationToken)
    {
        return _documentationCommentXml ?? "";
    }

    public string ToDisplayString(SymbolDisplayFormat format = null)
        => throw new NotImplementedException();

    public ImmutableArray<SymbolDisplayPart> ToDisplayParts(SymbolDisplayFormat format = null)
        => throw new NotImplementedException();

    public string ToMinimalDisplayString(SemanticModel semanticModel, int position, SymbolDisplayFormat format = null)
        => throw new NotImplementedException();

    public ImmutableArray<SymbolDisplayPart> ToMinimalDisplayParts(SemanticModel semanticModel, int position, SymbolDisplayFormat format = null)
        => throw new NotImplementedException();

    public virtual string MetadataName
    {
        get
        {
            return this.Name;
        }
    }

    public int MetadataToken => 0;

    public bool HasUnsupportedMetadata => false;

    public bool Equals(ISymbol other)
        => this.Equals((object)other);

    public bool Equals(ISymbol other, SymbolEqualityComparer equalityComparer)
        => this.Equals(other);
}