File: Emitter\Model\PropertySymbolAdapter.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.
 
#nullable disable
 
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.Cci;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.Emit;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
    internal partial class
#if DEBUG
        PropertySymbolAdapter : SymbolAdapter,
#else
        PropertySymbol :
#endif 
        IPropertyDefinition
    {
        public bool IsEncDeleted
            => false;
 
        #region IPropertyDefinition Members
 
        IEnumerable<IMethodReference> IPropertyDefinition.GetAccessors(EmitContext context)
        {
            CheckDefinitionInvariant();
 
            var getMethod = AdaptedPropertySymbol.GetMethod?.GetCciAdapter();
            if (getMethod != null && getMethod.ShouldInclude(context))
            {
                yield return getMethod;
            }
 
            var setMethod = AdaptedPropertySymbol.SetMethod?.GetCciAdapter();
            if (setMethod != null && setMethod.ShouldInclude(context))
            {
                yield return setMethod;
            }
 
            var sourceProperty = AdaptedPropertySymbol as SourcePropertySymbolBase;
            if ((object)sourceProperty != null && this.ShouldInclude(context))
            {
                SynthesizedSealedPropertyAccessor synthesizedAccessor = sourceProperty.SynthesizedSealedAccessorOpt;
                if ((object)synthesizedAccessor != null)
                {
                    yield return synthesizedAccessor.GetCciAdapter();
                }
            }
        }
 
        MetadataConstant IPropertyDefinition.DefaultValue
        {
            get
            {
                CheckDefinitionInvariant();
                return null;
            }
        }
 
        IMethodReference IPropertyDefinition.Getter
        {
            get
            {
                CheckDefinitionInvariant();
                MethodSymbol getMethod = AdaptedPropertySymbol.GetMethod;
                if ((object)getMethod != null || !AdaptedPropertySymbol.IsSealed)
                {
                    return getMethod?.GetCciAdapter();
                }
 
                return GetSynthesizedSealedAccessor(MethodKind.PropertyGet);
            }
        }
 
        bool IPropertyDefinition.HasDefaultValue
        {
            get
            {
                CheckDefinitionInvariant();
                return false;
            }
        }
 
        bool IPropertyDefinition.IsRuntimeSpecial
        {
            get
            {
                CheckDefinitionInvariant();
                return AdaptedPropertySymbol.HasRuntimeSpecialName;
            }
        }
 
        bool IPropertyDefinition.IsSpecialName
        {
            get
            {
                CheckDefinitionInvariant();
                return AdaptedPropertySymbol.HasSpecialName;
            }
        }
 
        ImmutableArray<IParameterDefinition> IPropertyDefinition.Parameters
        {
            get
            {
                CheckDefinitionInvariant();
#if DEBUG
                return AdaptedPropertySymbol.Parameters.SelectAsArray<ParameterSymbol, IParameterDefinition>(p => p.GetCciAdapter());
#else
                return StaticCast<IParameterDefinition>.From(AdaptedPropertySymbol.Parameters);
#endif
            }
        }
 
        IMethodReference IPropertyDefinition.Setter
        {
            get
            {
                CheckDefinitionInvariant();
                MethodSymbol setMethod = AdaptedPropertySymbol.SetMethod;
                if ((object)setMethod != null || !AdaptedPropertySymbol.IsSealed)
                {
                    return setMethod?.GetCciAdapter();
                }
 
                return GetSynthesizedSealedAccessor(MethodKind.PropertySet);
            }
        }
 
        #endregion
 
        #region ISignature Members
 
        [Conditional("DEBUG")]
        private void CheckDefinitionInvariantAllowEmbedded()
        {
            // can't be generic instantiation
            Debug.Assert(AdaptedPropertySymbol.IsDefinition);
 
            // must be declared in the module we are building
            Debug.Assert(AdaptedPropertySymbol.ContainingModule is SourceModuleSymbol || AdaptedPropertySymbol.ContainingAssembly.IsLinked);
        }
 
        CallingConvention ISignature.CallingConvention
        {
            get
            {
                CheckDefinitionInvariantAllowEmbedded();
                return AdaptedPropertySymbol.CallingConvention;
            }
        }
 
        ushort ISignature.ParameterCount
        {
            get
            {
                CheckDefinitionInvariant();
                return (ushort)AdaptedPropertySymbol.ParameterCount;
            }
        }
 
        ImmutableArray<IParameterTypeInformation> ISignature.GetParameters(EmitContext context)
        {
            CheckDefinitionInvariant();
#if DEBUG
            return AdaptedPropertySymbol.Parameters.SelectAsArray<ParameterSymbol, IParameterTypeInformation>(p => p.GetCciAdapter());
#else
            return StaticCast<IParameterTypeInformation>.From(AdaptedPropertySymbol.Parameters);
#endif
        }
 
        ImmutableArray<ICustomModifier> ISignature.ReturnValueCustomModifiers
        {
            get
            {
                CheckDefinitionInvariantAllowEmbedded();
                return AdaptedPropertySymbol.TypeWithAnnotations.CustomModifiers.As<ICustomModifier>();
            }
        }
 
        ImmutableArray<ICustomModifier> ISignature.RefCustomModifiers
        {
            get
            {
                CheckDefinitionInvariantAllowEmbedded();
                return AdaptedPropertySymbol.RefCustomModifiers.As<ICustomModifier>();
            }
        }
 
        bool ISignature.ReturnValueIsByRef
        {
            get
            {
                CheckDefinitionInvariantAllowEmbedded();
                return AdaptedPropertySymbol.RefKind.IsManagedReference();
            }
        }
 
        ITypeReference ISignature.GetType(EmitContext context)
        {
            CheckDefinitionInvariantAllowEmbedded();
            return ((PEModuleBuilder)context.Module).Translate(AdaptedPropertySymbol.Type,
                                                      syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNode,
                                                      diagnostics: context.Diagnostics);
        }
 
        #endregion
 
        #region ITypeDefinitionMember Members
 
        ITypeDefinition ITypeDefinitionMember.ContainingTypeDefinition
        {
            get
            {
                CheckDefinitionInvariant();
                return AdaptedPropertySymbol.ContainingType.GetCciAdapter();
            }
        }
 
        TypeMemberVisibility ITypeDefinitionMember.Visibility
        {
            get
            {
                CheckDefinitionInvariant();
                return AdaptedPropertySymbol.MetadataVisibility;
            }
        }
 
        #endregion
 
        #region ITypeMemberReference Members
 
        ITypeReference ITypeMemberReference.GetContainingType(EmitContext context)
        {
            CheckDefinitionInvariant();
            return AdaptedPropertySymbol.ContainingType.GetCciAdapter();
        }
 
        #endregion
 
        #region IReference Members
 
        void IReference.Dispatch(MetadataVisitor visitor)
        {
            CheckDefinitionInvariant();
            visitor.Visit((IPropertyDefinition)this);
        }
 
        IDefinition IReference.AsDefinition(EmitContext context)
        {
            CheckDefinitionInvariant();
            return this;
        }
 
        #endregion
 
        #region INamedEntity Members
 
        string INamedEntity.Name
        {
            get
            {
                CheckDefinitionInvariant();
                return AdaptedPropertySymbol.MetadataName;
            }
        }
 
        #endregion
 
        private IMethodReference GetSynthesizedSealedAccessor(MethodKind targetMethodKind)
        {
            var sourceProperty = AdaptedPropertySymbol as SourcePropertySymbolBase;
            if ((object)sourceProperty != null)
            {
                SynthesizedSealedPropertyAccessor synthesized = sourceProperty.SynthesizedSealedAccessorOpt;
                return (object)synthesized != null && synthesized.MethodKind == targetMethodKind ? synthesized.GetCciAdapter() : null;
            }
 
            return null;
        }
    }
 
    internal partial class PropertySymbol
    {
#if DEBUG
        private PropertySymbolAdapter _lazyAdapter;
 
        protected sealed override SymbolAdapter GetCciAdapterImpl() => GetCciAdapter();
 
        internal new PropertySymbolAdapter GetCciAdapter()
        {
            if (_lazyAdapter is null)
            {
                return InterlockedOperations.Initialize(ref _lazyAdapter, new PropertySymbolAdapter(this));
            }
 
            return _lazyAdapter;
        }
#else
        internal PropertySymbol AdaptedPropertySymbol => this;
 
        internal new PropertySymbol GetCciAdapter()
        {
            return this;
        }
#endif 
 
        internal virtual bool HasRuntimeSpecialName
        {
            get
            {
                CheckDefinitionInvariant();
                return false;
            }
        }
    }
 
#if DEBUG
    internal partial class PropertySymbolAdapter
    {
        internal PropertySymbolAdapter(PropertySymbol underlyingPropertySymbol)
        {
            AdaptedPropertySymbol = underlyingPropertySymbol;
 
            if (underlyingPropertySymbol is NativeIntegerPropertySymbol)
            {
                // Emit should use underlying symbol only.
                throw ExceptionUtilities.Unreachable();
            }
        }
 
        internal sealed override Symbol AdaptedSymbol => AdaptedPropertySymbol;
        internal PropertySymbol AdaptedPropertySymbol { get; }
    }
#endif
}