File: Symbols\Synthesized\SynthesizedEmbeddedMemorySafetyRulesAttributeSymbol.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;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.PooledObjects;
 
namespace Microsoft.CodeAnalysis.CSharp.Symbols;
 
// https://github.com/dotnet/roslyn/issues/82546: Confirm the attribute shape in BCL API review.
/// <summary>
/// <code>
/// namespace System.Runtime.CompilerServices
/// {
///     [CompilerGenerated, Microsoft.CodeAnalysis.Embedded]
///     [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
///     public sealed class MemorySafetyRulesAttribute : Attribute
///     {
///         public int Version { get; }
///         public MemorySafetyRulesAttribute(int version) { Version = version; }
///     }
/// }
/// </code>
/// </summary>
internal sealed class SynthesizedEmbeddedMemorySafetyRulesAttributeSymbol : SynthesizedEmbeddedAttributeSymbolBase
{
    private readonly ImmutableArray<FieldSymbol> _fields;
    private readonly ImmutableArray<PropertySymbol> _properties;
    private readonly ImmutableArray<MethodSymbol> _constructors;
 
    public SynthesizedEmbeddedMemorySafetyRulesAttributeSymbol(
        string name,
        NamespaceSymbol containingNamespace,
        ModuleSymbol containingModule,
        NamedTypeSymbol systemAttributeType,
        TypeSymbol int32Type)
        : base(name, containingNamespace, containingModule, baseType: systemAttributeType)
    {
        const string PropertyName = "Version";
 
        var field = new SynthesizedFieldSymbol(
            containingType: this,
            type: int32Type,
            name: GeneratedNames.MakeBackingFieldName(PropertyName),
            accessibility: DeclarationModifiers.Private,
            isReadOnly: true,
            isStatic: false);
 
        _fields = [field];
 
        _properties =
        [
            new SynthesizedPropertySymbol(PropertyName, field),
        ];
 
        _constructors =
        [
            new SynthesizedEmbeddedAttributeConstructorWithBodySymbol(
                containingType: this,
                getParameters: m => [SynthesizedParameterSymbol.Create(
                    container: m,
                    type: TypeWithAnnotations.Create(int32Type),
                    ordinal: 0,
                    refKind: RefKind.None,
                    name: "version")],
                getConstructorBody: GenerateConstructorBody),
        ];
    }
 
    internal override IEnumerable<FieldSymbol> GetFieldsToEmit() => _fields;
 
    public override ImmutableArray<MethodSymbol> Constructors => _constructors;
 
    internal override AttributeUsageInfo GetAttributeUsageInfo()
    {
        return new AttributeUsageInfo(AttributeTargets.Module, allowMultiple: false, inherited: false);
    }
 
    private void GenerateConstructorBody(SyntheticBoundNodeFactory factory, ArrayBuilder<BoundStatement> statements, ImmutableArray<ParameterSymbol> parameters)
    {
        Debug.Assert(_fields.Length == 1);
        Debug.Assert(parameters.Length == 1);
        statements.Add(
            factory.ExpressionStatement(
                factory.AssignmentExpression(
                    factory.Field(factory.This(), _fields[0]),
                    factory.Parameter(parameters[0]))));
    }
 
    private ArrayBuilder<T> GetMemberBuilder<T>(Func<Symbol, T> selector)
    {
        var builder = ArrayBuilder<T>.GetInstance(
            _fields.Length + _properties.Length * 2 + _constructors.Length);
 
        builder.AddRange(_fields, selector);
 
        builder.AddRange(_properties, selector);
 
        foreach (var property in _properties)
        {
            Debug.Assert(property.GetMethod is not null);
            Debug.Assert(property.SetMethod is null);
            builder.Add(selector(property.GetMethod));
        }
 
        builder.AddRange(_constructors, selector);
 
        return builder;
    }
 
    public override ImmutableArray<Symbol> GetMembers()
    {
        return GetMemberBuilder(static s => s).ToImmutableAndFree();
    }
 
    public override ImmutableArray<Symbol> GetMembers(string name)
    {
        var builder = GetMemberBuilder(static s => s);
        builder.RemoveAll(static (s, name) => s.Name != name, name);
        return builder.ToImmutableAndFree();
    }
 
    public override IEnumerable<string> MemberNames
    {
        get
        {
            return GetMemberBuilder(static s => s.Name).ToImmutableAndFree();
        }
    }
}