File: Emit\NoPia\CommonEmbeddedParameter.cs
Web Access
Project: src\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.
 
#nullable disable
 
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.Emit.NoPia
{
    internal abstract partial class EmbeddedTypesManager<
        TPEModuleBuilder,
        TModuleCompilationState,
        TEmbeddedTypesManager,
        TSyntaxNode,
        TAttributeData,
        TSymbol,
        TAssemblySymbol,
        TNamedTypeSymbol,
        TFieldSymbol,
        TMethodSymbol,
        TEventSymbol,
        TPropertySymbol,
        TParameterSymbol,
        TTypeParameterSymbol,
        TEmbeddedType,
        TEmbeddedField,
        TEmbeddedMethod,
        TEmbeddedEvent,
        TEmbeddedProperty,
        TEmbeddedParameter,
        TEmbeddedTypeParameter>
    {
        internal abstract class CommonEmbeddedParameter : Cci.IEmbeddedDefinition, Cci.IParameterDefinition
        {
            public readonly CommonEmbeddedMember ContainingPropertyOrMethod;
            public readonly TParameterSymbol UnderlyingParameter;
            private ImmutableArray<TAttributeData> _lazyAttributes;
 
            protected CommonEmbeddedParameter(CommonEmbeddedMember containingPropertyOrMethod, TParameterSymbol underlyingParameter)
            {
                this.ContainingPropertyOrMethod = containingPropertyOrMethod;
                this.UnderlyingParameter = underlyingParameter;
            }
 
            public bool IsEncDeleted
                => false;
 
            protected TEmbeddedTypesManager TypeManager
            {
                get
                {
                    return ContainingPropertyOrMethod.TypeManager;
                }
            }
 
            protected abstract bool HasDefaultValue { get; }
            protected abstract MetadataConstant GetDefaultValue(EmitContext context);
            protected abstract bool IsIn { get; }
            protected abstract bool IsOut { get; }
            protected abstract bool IsOptional { get; }
            protected abstract bool IsMarshalledExplicitly { get; }
            protected abstract Cci.IMarshallingInformation MarshallingInformation { get; }
            protected abstract ImmutableArray<byte> MarshallingDescriptor { get; }
            protected abstract string Name { get; }
            protected abstract Cci.IParameterTypeInformation UnderlyingParameterTypeInformation { get; }
            protected abstract ushort Index { get; }
            protected abstract IEnumerable<TAttributeData> GetCustomAttributesToEmit(TPEModuleBuilder moduleBuilder);
 
            private bool IsTargetAttribute(TAttributeData attrData, AttributeDescription description, out int signatureIndex)
            {
                return TypeManager.IsTargetAttribute(attrData, description, out signatureIndex);
            }
 
            private ImmutableArray<TAttributeData> GetAttributes(TPEModuleBuilder moduleBuilder, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics)
            {
                var builder = ArrayBuilder<TAttributeData>.GetInstance();
 
                // Copy some of the attributes.
 
                // Note, when porting attributes, we are not using constructors from original symbol.
                // The constructors might be missing (for example, in metadata case) and doing lookup
                // will ensure that we report appropriate errors.
 
                foreach (var attrData in GetCustomAttributesToEmit(moduleBuilder))
                {
                    int signatureIndex;
                    ImmutableArray<TypedConstant> constructorArguments;
                    ImmutableArray<KeyValuePair<string, TypedConstant>> namedArguments;
 
                    if (IsTargetAttribute(attrData, AttributeDescription.ParamArrayAttribute, out signatureIndex))
                    {
                        if (signatureIndex == 0 && TypeManager.TryGetAttributeArguments(attrData, out constructorArguments, out namedArguments, syntaxNodeOpt, diagnostics))
                        {
                            builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_ParamArrayAttribute__ctor, constructorArguments, namedArguments, syntaxNodeOpt, diagnostics));
                        }
                    }
                    else if (IsTargetAttribute(attrData, AttributeDescription.DateTimeConstantAttribute, out signatureIndex))
                    {
                        if (signatureIndex == 0 && TypeManager.TryGetAttributeArguments(attrData, out constructorArguments, out namedArguments, syntaxNodeOpt, diagnostics))
                        {
                            builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_CompilerServices_DateTimeConstantAttribute__ctor, constructorArguments, namedArguments, syntaxNodeOpt, diagnostics));
                        }
                    }
                    else if (IsTargetAttribute(attrData, AttributeDescription.DecimalConstantAttribute, out signatureIndex))
                    {
                        if ((signatureIndex == 0 || signatureIndex == 1) && TypeManager.TryGetAttributeArguments(attrData, out constructorArguments, out namedArguments, syntaxNodeOpt, diagnostics))
                        {
                            builder.AddOptional(TypeManager.CreateSynthesizedAttribute(
                                signatureIndex == 0 ? WellKnownMember.System_Runtime_CompilerServices_DecimalConstantAttribute__ctor :
                                    WellKnownMember.System_Runtime_CompilerServices_DecimalConstantAttribute__ctorByteByteInt32Int32Int32,
                                constructorArguments, namedArguments, syntaxNodeOpt, diagnostics));
                        }
                    }
                    else if (IsTargetAttribute(attrData, AttributeDescription.DefaultParameterValueAttribute, out signatureIndex))
                    {
                        if (signatureIndex == 0 && TypeManager.TryGetAttributeArguments(attrData, out constructorArguments, out namedArguments, syntaxNodeOpt, diagnostics))
                        {
                            builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_InteropServices_DefaultParameterValueAttribute__ctor, constructorArguments, namedArguments, syntaxNodeOpt, diagnostics));
                        }
                    }
                }
 
                return builder.ToImmutableAndFree();
            }
 
            bool Cci.IParameterDefinition.HasDefaultValue
            {
                get
                {
                    return HasDefaultValue;
                }
            }
 
            MetadataConstant Cci.IParameterDefinition.GetDefaultValue(EmitContext context)
            {
                return GetDefaultValue(context);
            }
 
            bool Cci.IParameterDefinition.IsIn
            {
                get
                {
                    return IsIn;
                }
            }
 
            bool Cci.IParameterDefinition.IsOut
            {
                get
                {
                    return IsOut;
                }
            }
 
            bool Cci.IParameterDefinition.IsOptional
            {
                get
                {
                    return IsOptional;
                }
            }
 
            bool Cci.IParameterDefinition.IsMarshalledExplicitly
            {
                get
                {
                    return IsMarshalledExplicitly;
                }
            }
 
            Cci.IMarshallingInformation Cci.IParameterDefinition.MarshallingInformation
            {
                get
                {
                    return MarshallingInformation;
                }
            }
 
            ImmutableArray<byte> Cci.IParameterDefinition.MarshallingDescriptor
            {
                get
                {
                    return MarshallingDescriptor;
                }
            }
 
            IEnumerable<Cci.ICustomAttribute> Cci.IReference.GetAttributes(EmitContext context)
            {
                if (_lazyAttributes.IsDefault)
                {
                    var diagnostics = DiagnosticBag.GetInstance();
                    var attributes = GetAttributes((TPEModuleBuilder)context.Module, (TSyntaxNode)context.SyntaxNode, diagnostics);
 
                    if (ImmutableInterlocked.InterlockedInitialize(ref _lazyAttributes, attributes))
                    {
                        // Save any diagnostics that we encountered.
                        context.Diagnostics.AddRange(diagnostics);
                    }
 
                    diagnostics.Free();
                }
 
                return _lazyAttributes;
            }
 
            void Cci.IReference.Dispatch(Cci.MetadataVisitor visitor)
            {
                throw ExceptionUtilities.Unreachable();
            }
 
            Cci.IDefinition Cci.IReference.AsDefinition(EmitContext context)
            {
                return this;
            }
 
            CodeAnalysis.Symbols.ISymbolInternal Cci.IReference.GetInternalSymbol() => null;
 
            string Cci.INamedEntity.Name
            {
                get { return Name; }
            }
 
            ImmutableArray<Cci.ICustomModifier> Cci.IParameterTypeInformation.CustomModifiers
            {
                get
                {
                    return UnderlyingParameterTypeInformation.CustomModifiers;
                }
            }
 
            bool Cci.IParameterTypeInformation.IsByReference
            {
                get
                {
                    return UnderlyingParameterTypeInformation.IsByReference;
                }
            }
 
            ImmutableArray<Cci.ICustomModifier> Cci.IParameterTypeInformation.RefCustomModifiers
            {
                get
                {
                    return UnderlyingParameterTypeInformation.RefCustomModifiers;
                }
            }
 
            Cci.ITypeReference Cci.IParameterTypeInformation.GetType(EmitContext context)
            {
                return UnderlyingParameterTypeInformation.GetType(context);
            }
 
            ushort Cci.IParameterListEntry.Index
            {
                get
                {
                    return Index;
                }
            }
 
            /// <remarks>
            /// This is only used for testing.
            /// </remarks>
            public override string ToString()
            {
                return ((ISymbol)UnderlyingParameter).ToDisplayString(SymbolDisplayFormat.ILVisualizationFormat);
            }
 
            public sealed override bool Equals(object obj)
            {
                // It is not supported to rely on default equality of these Cci objects, an explicit way to compare and hash them should be used.
                throw Roslyn.Utilities.ExceptionUtilities.Unreachable();
            }
 
            public sealed override int GetHashCode()
            {
                // It is not supported to rely on default equality of these Cci objects, an explicit way to compare and hash them should be used.
                throw Roslyn.Utilities.ExceptionUtilities.Unreachable();
            }
        }
    }
}