File: Symbols\Synthesized\SynthesizedEmbeddedExtensionMarkerNameAttributeSymbol.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
{
    internal sealed class SynthesizedEmbeddedExtensionMarkerAttributeSymbol : SynthesizedEmbeddedAttributeSymbolBase
    {
        private readonly ImmutableArray<MethodSymbol> _constructors;
        private readonly SynthesizedFieldSymbol _nameField;
        private readonly SynthesizedPropertySymbol _nameProperty;
 
        private const string PropertyName = "Name";
        private const string FieldName = "<Name>k__BackingField";
 
        public SynthesizedEmbeddedExtensionMarkerAttributeSymbol(
            string name,
            NamespaceSymbol containingNamespace,
            ModuleSymbol containingModule,
            NamedTypeSymbol systemAttributeType,
            TypeSymbol systemStringType)
            : base(name, containingNamespace, containingModule, baseType: systemAttributeType)
        {
            Debug.Assert(FieldName == GeneratedNames.MakeBackingFieldName(PropertyName));
 
            _nameField = new SynthesizedFieldSymbol(this, systemStringType, FieldName, isReadOnly: true);
            _nameProperty = new SynthesizedPropertySymbol(PropertyName, _nameField);
            _constructors = [new SynthesizedEmbeddedAttributeConstructorWithBodySymbol(this, getConstructorParameters, getConstructorBody)];
 
            // Ensure we never get out of sync with the description
            Debug.Assert(_constructors.Length == AttributeDescription.ExtensionMarkerAttribute.Signatures.Length);
 
            ImmutableArray<ParameterSymbol> getConstructorParameters(MethodSymbol ctor)
            {
                return [SynthesizedParameterSymbol.Create(ctor, TypeWithAnnotations.Create(systemStringType), ordinal: 0, RefKind.None, name: "name")];
            }
 
            void getConstructorBody(SyntheticBoundNodeFactory f, ArrayBuilder<BoundStatement> statements, ImmutableArray<ParameterSymbol> parameters)
            {
                // this._namedField = name;
                statements.Add(f.Assignment(
                    f.Field(f.This(), this._nameField),
                    f.Parameter(parameters[0])));
            }
        }
 
        public override ImmutableArray<MethodSymbol> Constructors => _constructors;
 
        internal override AttributeUsageInfo GetAttributeUsageInfo()
        {
            return new AttributeUsageInfo(
                AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property |
                AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate,
                allowMultiple: false, inherited: false);
        }
 
        internal override IEnumerable<FieldSymbol> GetFieldsToEmit()
        {
            return [_nameField];
        }
 
        public override ImmutableArray<Symbol> GetMembers()
            => [_nameField, _nameProperty, _nameProperty.GetMethod, _constructors[0]];
 
        public override ImmutableArray<Symbol> GetMembers(string name)
        {
            return name switch
            {
                FieldName => [_nameField],
                PropertyName => [_nameProperty],
                WellKnownMemberNames.InstanceConstructorName => ImmutableArray<Symbol>.CastUp(_constructors),
                _ => []
            };
        }
 
        public override IEnumerable<string> MemberNames
            => [FieldName, PropertyName, WellKnownMemberNames.InstanceConstructorName];
    }
}