File: Symbols\Source\SourceNamedTypeSymbol_Enum.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.Diagnostics;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
 
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
    internal partial class SourceNamedTypeSymbol
    {
        private SynthesizedEnumValueFieldSymbol _lazyEnumValueField;
        private NamedTypeSymbol _lazyEnumUnderlyingType = ErrorTypeSymbol.UnknownResultType;
 
        /// <summary>
        /// For enum types, gets the underlying type. Returns null on all other
        /// kinds of types.
        /// </summary>
        public override NamedTypeSymbol EnumUnderlyingType
        {
            get
            {
                if (ReferenceEquals(_lazyEnumUnderlyingType, ErrorTypeSymbol.UnknownResultType))
                {
                    BindingDiagnosticBag diagnostics = BindingDiagnosticBag.GetInstance();
                    if ((object)Interlocked.CompareExchange(ref _lazyEnumUnderlyingType, this.GetEnumUnderlyingType(diagnostics), ErrorTypeSymbol.UnknownResultType) ==
                        (object)ErrorTypeSymbol.UnknownResultType)
                    {
                        AddDeclarationDiagnostics(diagnostics);
                        this.state.NotePartComplete(CompletionPart.EnumUnderlyingType);
                    }
                    diagnostics.Free();
                }
 
                return _lazyEnumUnderlyingType;
            }
        }
 
        private NamedTypeSymbol GetEnumUnderlyingType(BindingDiagnosticBag diagnostics)
        {
            if (this.TypeKind != TypeKind.Enum)
            {
                return null;
            }
 
            var compilation = this.DeclaringCompilation;
            var decl = this.declaration.Declarations[0];
            var bases = GetBaseListOpt(decl);
            if (bases != null)
            {
                var types = bases.Types;
                if (types.Count > 0)
                {
                    var typeSyntax = types[0].Type;
 
                    var baseBinder = compilation.GetBinder(bases);
                    var type = baseBinder.BindType(typeSyntax, diagnostics).Type;
 
                    // Error types are not exposed to the caller. In those
                    // cases, the underlying type is treated as int.
                    if (!type.SpecialType.IsValidEnumUnderlyingType())
                    {
                        diagnostics.Add(ErrorCode.ERR_IntegralTypeExpected, typeSyntax.Location);
                        type = compilation.GetSpecialType(SpecialType.System_Int32);
                    }
 
                    return (NamedTypeSymbol)type;
                }
            }
 
            NamedTypeSymbol defaultUnderlyingType = compilation.GetSpecialType(SpecialType.System_Int32);
            Binder.ReportUseSite(defaultUnderlyingType, diagnostics, this.GetFirstLocation());
            return defaultUnderlyingType;
        }
 
        /// <summary>
        /// For enum types, returns the synthesized instance field used
        /// for generating metadata. Returns null for non-enum types.
        /// </summary>
        internal FieldSymbol EnumValueField
        {
            get
            {
                if (this.TypeKind != TypeKind.Enum)
                {
                    return null;
                }
 
                if ((object)_lazyEnumValueField == null)
                {
                    Debug.Assert((object)this.EnumUnderlyingType != null);
                    Interlocked.CompareExchange(ref _lazyEnumValueField, new SynthesizedEnumValueFieldSymbol(this), null);
                }
 
                return _lazyEnumValueField;
            }
        }
    }
}